Set

Set是继承了Collection接口的抽象接口,不包含重复元素的集合。简单地说,集合不包含一对元素e1和e2,例如e1.equals(e2),最多包含一个空元素。


目录

  • Set
  • 一、Set
  • 二、TreeSet
  • 三、比较器Comparable和Comparator
  • 四、HashSet

一、Set


/*
* Set元素特点:无序(添加顺序)不可重复
*   TreeSet: 底层红黑树
*   HashSet: 底层散列表
* */
public class _01_Collection_Set {public static void main(String[] args) {TreeSet<Object> treeSet = new TreeSet<>();treeSet.add(1);treeSet.add(2);System.out.println(treeSet.size());for (Object o : treeSet) {System.out.println(o);}}
}

二、TreeSet


/*
* TreeSet:元素不可重复,添加的元素会按照某种规则自动排序
*   想要使用TreeSet,元素必须要排序
*       数字:默认从小到大
*       字符串:默认比较每位ASCII码
*       日期:默认比较自然日期 昨天、今天、明天
* */
public class _02_Collection_TreeSet {public static void main(String[] args) {TreeSet<Object> treeSet = new TreeSet<>();treeSet.add(1);treeSet.add(5);treeSet.add(2);treeSet.add(9);// 上面添加的是数字,下面如果是字符串就会报错,因为添加的时候需要比较元素大小// 而 不同类型 元素,没有可比性// treeSet.add("aaa");for (Object o : treeSet) {System.out.println(o);}System.out.println("-------");TreeSet<Object> treeSet2 = new TreeSet<>();treeSet2.add("a");treeSet2.add("1");// 如果有多个字符,先比较第一位,如果第一位不同,则第一位小的在上面// 如果第一位相同,在比较第二位,依次类推treeSet2.add("11"); // 第一位为1,其ASCII码值为47,a的ASCII值97treeSet2.add("101");treeSet2.add("b");treeSet2.add("c");for (Object o : treeSet2) {System.out.print(o + " "); // 输出:1 101 11 a b c}}
}

三、比较器Comparable和Comparator


/*
* Comparable
*   比较器有两种:1 元素自身比较器 2 比较器类
*   为什么字符串、Integer、Date可以排序?
*       因为都实现了 implement Comparable
*   使用TreeSet在进行数据添加的时候,会自动调用该对象的comparableTo()方法
*       和集合中元素进行比较
*       如果想要存储自定义类型?需要实现该接口
* */
public class _03_Collection_TreeSet {public static void main(String[] args) {TreeSet<Object> treeSet = new TreeSet<>();User user = new User(10);// 类型转换异常java.lang.ClassCastException:// com.tianl.Collection.Set.User cannot be cast to java.lang.Comparable// User必须实现Comparable接口才能存入TreeSet,添加的时候,会自动调用该对象的comparableTo()方法// 没有实现comparableTo()方法,则不能添加入TreeSet// treeSet.add(user);treeSet.add(new User(12));treeSet.add(new User(13));treeSet.add(new User(15));// treeSet.add(1); // 重复存入无效System.out.println(treeSet.size());for (Object o : treeSet) {System.out.println(o);}}
}class User implements Comparable{private int age;public User(int age) {this.age = age;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic int compareTo(Object obj) {// this表示当前对象// obj 表示集合内对象// 返回值为0 表示 相等 ,则不添加// 返回大于0 表示 要添加的元素大,则放在后面// 返回小于0 表示 要添加的元素小,则放在前面User other = (User) obj;return this.age - other.age; // 升序,// return other.age - this.age; // 升序,}@Overridepublic String toString() {return "User: [age=" + age + "]";}
}/*// TreeSet中add方法源码,底层红黑树public boolean add(E e) {return m.put(e, PRESENT)==null;}public V put(K key, V value) {Entry<K,V> t = root;if (t == null) {compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null);size = 1;modCount++;return null;}int cmp;Entry<K,V> parent;// split comparator and comparable pathsComparator<? super K> cpr = comparator;if (cpr != null) {do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}else {if (key == null)throw new NullPointerException();@SuppressWarnings("unchecked")Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t;cmp = k.compareTo(t.key); // 自动调用该对象的comparableTo()方法if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;fixAfterInsertion(e);size++;modCount++;return null;}
* */

/*
* TreeSet添加元素必须排序
*   实现排序的两种方法
*       1 要添加的元素对应的类实现java.lang.Comparable接口,并实现comparableTo()方法
*       2 使用java.util.Comparator比较器类
*   Comparable:添加元素实现该接口并覆写comparableTo()方法
*   Comparator:第三方比较器类,应用于:Integer默认升序,如何实现降序?使用Comparator进行降序排序
*
* 如果添加元素的类 是 自定义类, 应该使用Comparable,可对扩展开放,其他人还可以使用Comparator实现新的排序
* 如果添加元素的类 不是 自定义类,
*    1 该类有排序(实现了Comparable),如Integer,但默认排序不满足需求
*       则可以使用Comparator调整排序,其优先级高
*    2 该类没有实现排序(没有实现Comparable),则需要使用Comparator进行排序,因为不可能修改源码实现
* */
public class _04_Collection_TreeSet {public static void main(String[] args) {// TreeSet<Object> treeSet = new TreeSet<>(); // 默认升序// 实现Comparator接口compare()方法传入//TreeSet<Object> treeSet = new TreeSet<>(new SortTest());// 匿名内部类写法传入TreeSet<Object> treeSet = new TreeSet<>(new Comparator<Object>() {@Overridepublic int compare(Object o1, Object o2) {Integer i1 = (Integer) o1;Integer i2 = (Integer) o2;return i2 - i1;}}); // 实现降序treeSet.add(2);treeSet.add(4);treeSet.add(8);treeSet.add(16);for (Object o : treeSet) {System.out.println(o);}}
}// 比较器类
class SortTest implements Comparator{@Overridepublic int compare(Object o1, Object o2) {Integer i1 = (Integer) o1;Integer i2 = (Integer) o2;return i2 - i1;}
}

/*
* TreeSet中使用Comparator排序demo实现多属性比较
* */
public class _01_Collection_Sort {public static void main(String[] args) {// ComparatorTreeSet<Object> treeSet = new TreeSet<>(new Comparator<Object>() {@Overridepublic int compare(Object o1, Object o2) {Student s1 = (Student) o1;Student s2 = (Student) o2;if (s1.getId() > s2.getId()) {return 1;} else if (s1.getId() < s2.getId()) {return -1;} else {return s1.getAge() - s2.getAge(); // ID相同情况返回}}});treeSet.add(new Student(3,18,"AAA"));treeSet.add(new Student(2,13,"AAB"));treeSet.add(new Student(1,21,"AAC"));treeSet.add(new Student(5,28,"AAG"));treeSet.add(new Student(4,25,"AAD"));treeSet.add(new Student(4,22,"AAE"));treeSet.add(new Student(4,31,"AAF"));for (Object o : treeSet) {System.out.println(o);}}
}// Student类中没有实现Comparable接口,则必须使用Comparator接口才能实现排序
class Student{private int id;private int age;private String name;public Student(int id, int age, String name) {this.id = id;this.age = age;this.name = name;}@Overridepublic String toString() {return "id: " + id + ", age: " + age + ", name: " + name;}public int getId() {return id;}public void setId(int id) {this.id = id;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

/*
* List排序,想要实现排序,元素必须实现Comparable方法
* */
public class _02_Collection_Sort {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(1);arrayList.add(21);arrayList.add(16);arrayList.add(11);// 可以使用 Collections 包中的sort方法排序,是因为Integer中实现了Comparable接口Collections.sort(arrayList);System.out.println(arrayList);}
}

/*
* 默认排序不满足需求,或者没有实现Comparable排序接口
*   则使用Comparator接口实现
* */
public class _03_Collection_Sort {public static void main(String[] args) {ArrayList<Integer> arrayList = new ArrayList<>();arrayList.add(10);arrayList.add(1);arrayList.add( 16);arrayList.add(31);// 使用Comparator接口实现降序// 不改变源码条件下实现重新排序Collections.sort(arrayList, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {Integer i1 = (Integer) o1;Integer i2 = (Integer) o2;return i2 - i1;}});System.out.println(arrayList);}
}

/*
* ArrayList下 需求:在main方法中,不改变其他源码情况下,输出语句按照年龄排序
* */
public class _04_Collection_SortTest {public static void main(String[] args) {ArrayList<Object> arrayList = new ArrayList<>();arrayList.add(new Person("AAA",18));arrayList.add(new Person("BBB",28));arrayList.add(new Person("CCC",8));arrayList.add(new Person("DDD",8)); // 可重复// Comparator接口实现按照年龄排序Collections.sort(arrayList,new Comparator<Object>() {@Overridepublic int compare(Object o1, Object o2) {Person p1 = (Person) o1;Person p2 = (Person) o2;// return Integer.compare(p1.getAge(), p2.getAge())// 下面是上面语句的详细形式if (p1.getAge() > p2.getAge()){return 1; // 返回正数放在后边} else if (p1.getAge() < p2.getAge()){return -1; // 返回正数放在前边} else {return 0; // 相等}}});for (Object o : arrayList) {System.out.println(o);}System.out.println("-----------");for (Object o : arrayList) {Person person = (Person) o;System.out.println("name: "+person.getName()+", age: "+person.getAge());}}
}class Person{private int age;private String name;@Overridepublic String toString() {return "name: " + name + ", age: " + age;}public Person() {}public Person(String name) {this.name = name;}public Person(String name, int age) {this.age = age;this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

四、HashSet


/*
* hash算法:一种安全的加密算法,把不定长值变为定长值,不能保证唯一性
*
* 散列表:
*   数组中 保存链表() 单向链表,并且链表节点内有四个属性
*       1、key 2、value 3、next 4、hash
*   散列表是一种数据结构,在Java中被封装到HashSet、HashMap、HashTable中
*       HashTable过时
*   hash算法在Java中是指 hashCode 函数及重写
*   目的:为了查询快,因为hash值是一个固定的值
*
* 1 hash过程
*   获取对象,调用对象自身的hashCode()方法,进行hash算法,得到数组下标,把hash值保存到对应数组中
*   Set特性:无序(添加顺序),不可重复(先hashCode比较,若hash值相等,在equals比较)
* 2 HashSet和HashMap
*   HashSet是HashMap的封装,本质是一个HashMap
*   默认初始化容量都是 16
*   封装之后HashSet把value值屏蔽了,只能操作key。
*   所以在使用HashSet添加的时候,只需要传入key即可
* 3 HashSet添加过程
*   1 使用添加的键值对中的key,调用key的hashCode方法,生成hash值,进行hash算法得到数组下标
*       判断该下标上是否有元素,如果没有,把 键值对 保存到该数组中即可
*   2 如果该数组中有对象,则调用key的equals方法和数组中元素进行比较
*       如果相等则key不添加,value值覆盖
*   3 如果不等,则把 该对象 添加到已有元素的next属性,形成链表
*   4 如果添加时,已经是链表,则需要使用key和链表中所有元素的key进行比较是否相等
*
* 散列表中需要使用hashCode和equals来表示对象的唯一性
*   在添加自定义类型元素的时候,需要考虑按需求重写hashCode和equals方法
* */
public class _05_Collection_hashSet {public static void main(String[] args) {HashSet<Object> hashSet = new HashSet<>();hashSet.add(111);hashSet.add(222);hashSet.add("xxx");// hashSet.add("xxx"); // 相同不添加for (Object o : hashSet) {System.out.println(o);}}
}

/*
* 按需求重写hashCode和equals方法实现hashSet排序
* */
public class _06_Collection_hashSet {public static void main(String[] args) {HashSet<Object> hashSet = new HashSet<>();hashSet.add(new Employee("30","不可计数V字领"));hashSet.add(new Employee("45","护服务"));hashSet.add(new Employee("83","v哈哈ds,,"));hashSet.add(new Employee("18","AAA"));hashSet.add(new Employee("19","BBB"));hashSet.add(new Employee("20","CCC0"));hashSet.add(new Employee("20","CCC1")); // 不添加,比较的是numberhashSet.add(new Employee("20","CCC2")); // 需求中:number相同则是同一个对象for (Object o : hashSet) {System.out.println(o);}}
}class Employee{private String number;private String name;public Employee(String number, String name) {this.number = number;this.name = name;}@Overridepublic int hashCode() {System.out.println("hashCode()方法执行");return number.hashCode(); // 只根据number属性判断自定义类类型}@Overridepublic boolean equals(Object obj) {System.out.println("equals方法执行");if (this == obj) return true;if (obj == null) return false;if (obj instanceof Employee){Employee other = (Employee) obj;return other.getNumber().equals(this.number);}return false;}@Overridepublic String toString() {return "number: " + number + ", name: " + name;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

Java集合中Set相关推荐

  1. Java - Java集合中的安全失败Fail Safe机制 (CopyOnWriteArrayList)

    文章目录 Pre 概述 fail-safe的容器-CopyOnWriteArrayList add remove函数 例子 缺陷 使用场景 Pre Java - Java集合中的快速失败Fail Fa ...

  2. 三十九、Java集合中的HashSet和TreeSet

    @Author:Runsen @Date:2020/6/6 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排名 ...

  3. 如何将java集合中重复的元素取出来

    今天就给大家讲一下如何将java集合中重复的元素取出来 不多废话,直接代码 此处是对集合中的数字进行查找,其他类型照样适用! List<Integer> list = new ArrayL ...

  4. Java 集合框架分析:JAVA集合中的一些边边角角的知识

    相关文章: Java 集合框架分析:Set http://blog.csdn.net/youyou1543724847/article/details/52733723 Java 集合框架分析:Lin ...

  5. 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法

    注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...

  6. Java集合中contains方法的效率对比

    Java集合中contains方法的效率对比 Java集合List.Set中均有对集合中元素是否存在的判断方法contains(Object o):Map中有对key及value是否存在的判断方法co ...

  7. java集合中的泛型的使用

    -----------------------java集合中的泛型的使用------------------------ 我们在项目中使用集合基本99%都是在集合中存储同一种数据类型.既然我们在集合中 ...

  8. 考考基础部分,谈谈Java集合中HashSet的原理及常用方法

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:工匠初心 cnblogs.com/LiaHon/p/1125 ...

  9. 吃透Java集合中的Set集合必备文章,快快收藏

    零基础学习Java之Set集合 概述 Set的使用 常用方法介绍 Set集合的遍历 代码实例 Set的实现类 HashSet 基本介绍 代码示例 LinkedHashSet 基本介绍 代码示例 Tre ...

  10. (020)java后台开发之JAVA集合中的List接口

    转载:http://blog.csdn.net/self_realian/article/details/51881977 原文写的很好.请看原文. JAVA中的集合类: JAVA中的集合类,是一种工 ...

最新文章

  1. 统计文本中出现的单词个数频率
  2. 简单删除我的电脑里的wps云文档图标
  3. MFC的exe启动时提示应用程序配置不正确,应用程序未能启动错误
  4. emui华为java2p_大文件包来了!两款华为手机依然在更新,EMUI两大功能很实用
  5. ABB 机器人 IRBP系列转台的一段代码注释
  6. zipkin 自定义采样率_分组,采样和批处理– Java 8中的自定义收集器
  7. 2018.09.24 codeforces 1053C. Putting Boxes Together(线段树)
  8. PowerDesigner--创建概念数据模型;并生成逻辑数据模型/物理数据模型/数据库SQL脚本
  9. R语言 需要安装的包
  10. 什么是港美股窝轮(Warrants)?
  11. 数字图像处理(2)——数字图像获取
  12. oracle查询asm的绝对路径,查找ASM 1号文件位置
  13. 谷歌图片的爬虫库(附加必应图片爬虫)--针对近期谷歌变了
  14. 目标检测: 一文读懂 CenterNet (CVPR 2019)
  15. Windows10远程登陆Ubuntu桌面
  16. bzoj 1778 [Usaco2010 Hol]Dotp 驱逐猪猡
  17. Python图形用户界面
  18. Vue实现视频播放(video.js)
  19. 如何看懂照片的直方图?
  20. 手机号码批量导入通讯录php,怎么从电脑上的excel表格的手机号码导入通讯录到华为手机:...

热门文章

  1. WordPress初学者入门教程-“经典”所见即所得编辑器
  2. teamview删除设备
  3. 微信小程序播放m3u8视频总结
  4. P1567 统计天数(C语言)
  5. win10-2016企业版长期服务版激活
  6. Mob第三方登录快速集成开发
  7. 疫情之下,普通人高薪就业指南:学软件测试,路就不会遥远
  8. URI API——公交、驾车、步行导航
  9. VS Code语言切换
  10. python爬取微博图片教程_Python爬取微博实例分析