发布于2021-05-29 22:40 阅读(1449) 评论(0) 点赞(29) 收藏(1)
Set容器是一个不包含重复元素的Collection,并且最多包含一个null元素,它和List容器相反,Set容器不能保证其元素的顺序。
最常用的两个Set接口的实现类是HashSet和TreeSet.
HashSet扩展AbstractSet并且实现Set接口
HashSet使用散列表(又称哈希表)进行存储
构造方法:
HashSet() | 默认构造方法 |
HashSet(Collection c) | 使用collection集合进行初始化 |
HashSet(int capacity) | 指定初始数组的大小 |
HashSet(int capacity, float fillRatio) | 指定初始数组的大小和扩容因子 |
HashSet没有定义任何超过它的父类和接口提供的其他方法
散列集合没有确保其元素的顺序,因为散列处理通常不参与排序,而且每次有新的元素加入的时候,顺序也会发生改变。
散列集合不保证它的元素的顺序。元素加入散列集合的顺序并不一定是他们被迭代读出的顺序。
自定义类作为HashSet的元素的时候,规定要重写类的hashCode() 和 equals() 两个方法。
HashSet通过元素的hashCode() 和 equals() 两个方法判断元素是否相同,如果元素的hashCode()方法相同且equals()也相等,那么HashMap就认为元素是相等的。
总结:HashSet的内部操作的底层数据是HashMap,只是我们操作的是HashMap的Key。
- @Getter
- @AllArgsConstructor
- static class Student implements Comparable<Student>{
- private String name;
- private Integer age;
-
-
- @Override
- public String toString() {
- return "Student{" +
- "name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- Student student = (Student) o;
- return Objects.equals(name, student.name) &&
- Objects.equals(age, student.age);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(name, age);
- }
-
- @Override
- public int compareTo(Student o) {
- return this.getName().compareTo(o.getName());
- }
- }
示例1:
- @Test
- public void hashSet(){
- Set<Student> set = new HashSet<>();
- Student stu1 = new Student("唐三", 25);
- Student stu2 = new Student("比比东", 50);
- Student stu3 = new Student("千道流", 130);
- Student stu4 = new Student("波塞西", 200);
- Student stu5 = new Student("唐三", 25);
-
- set.add(stu1);
- set.add(stu2);
- set.add(stu3);
- set.add(stu4);
- System.out.println(set.add(stu5));
-
- System.out.println(set);
-
- }
-
- 输出内容:
- false
- [Student{name='比比东', age=50}, Student{name='千道流', age=130}, Student{name='唐三', age=25}, Student{name='波塞西', age=200}]
上面实例中,姓名为“唐三”的student在第二次加入的时候是失败的,所以add方法返回false,HashMap在判定key相等的时候,会进行值的替换,HashSet在判定Key相等的时候,后面的值会被忽略掉。
TreeSet为使用树来进行存储的Set接口提供了一个工具,对象安升序存储,访问和检索很快
在存储了大量的需要进行快速检索的排序信息的情况下,TreeSet是一个很好的选择。
构造方法:
TreeSet() | 默认构造方法 |
TreeSet(Collection c) | 使用一个Collection对象进行初始化 |
TreeSet(Comparator comp) | 构造TreeSet,并传入比较对象Comparator |
TreeSet(SortedSet ss) |
TreeSet使用Comparator的compare方法(或者元素所属类型实现Comparable接口的compareTo方法)判断元素是否相等,元素是否相等与hashCode() 和 equals() 两个方法没有任何关系,如果compare()或者compareTo()方法返回0就表示元素是相等的。
在创建TreeSet的时候,要么传入Comparator的实现类,要么元素的所属类实现Comparable的compareTo方法,二者必须选择一个;且如果二者同时满足,会选择传入的Comparator的实现类进行元素的比较。
Comparator#compare:
Comparable#compareTo:
总结:TreeSet的内部操作的底层数据是TreeMap,只是我们操作的是TreeMap的key。
示例2:
- @Test
- public void treeSet(){
- Set<Student> set = new TreeSet<>();
- Student stu1 = new Student("tangsan", 25);
- Student stu2 = new Student("bibidong", 50);
- Student stu3 = new Student("qiandaoliu", 130);
- Student stu4 = new Student("bosaixi", 200);
- Student stu5 = new Student("tangsan", 26);
-
- set.add(stu1);
- set.add(stu2);
- set.add(stu3);
- set.add(stu4);
- System.out.println(set.add(stu5));
-
- System.out.println(set);
-
- }
-
- 输出内容:
- false
- [Student{name='bibidong', age=50}, Student{name='bosaixi', age=200}, Student{name='qiandaoliu', age=130}, Student{name='tangsan', age=25}]
Student实现comparable接口的compareTo时,使用的时用户姓名座对比,所以两个“tangsan”student,只有第一次的被存储。第二次存储“tangsan”时返回false。
示例3:
- @Test
- public void treeSet(){
- Set<Student> set = new TreeSet<>(new Comparator<Student>() {
- @Override
- public int compare(Student s1, Student s2) {
- if(s1.getName().compareTo(s2.getName()) > 0){
- return 1;
- } else if (s1.getName().compareTo(s2.getName()) < 0){
- return -1;
- } else {
- return s1.getAge().compareTo(s2.getAge());
- }
- }
- });
- Student stu1 = new Student("tangsan", 25);
- Student stu2 = new Student("bibidong", 50);
- Student stu3 = new Student("qiandaoliu", 130);
- Student stu4 = new Student("bosaixi", 200);
- Student stu5 = new Student("tangsan", 26);
-
- set.add(stu1);
- set.add(stu2);
- set.add(stu3);
- set.add(stu4);
- System.out.println(set.add(stu5));
-
- System.out.println(set);
-
- }
-
- 输出内容:
- [Student{name='bibidong', age=50}, Student{name='bosaixi', age=200}, Student{name='qiandaoliu', age=130}, Student{name='tangsan', age=25}, Student{name='tangsan', age=26}]
上面示例中传入了Comparator对象,如果传入Comparator对象,那么就不会再使用自然顺序进行排序,Comparator在实现的时候,先使用姓名进行对比,在姓名相同的时候,使用年龄进行对比。所以上面的示例中两个“tangsan”都成功存储,而且25岁的在前,26岁的在后。
LinkedHashSet是基于HashSet实现的,所以特性参考HashSet就行,唯一的区别就是LinkedHashSet可以保证输入顺序和输出顺序保持一致。
示例:
- @Test
- public void linkedHashSet(){
- Set<Student> set = new LinkedHashSet<>();
- Student stu1 = new Student("唐三", 25);
- Student stu2 = new Student("比比东", 50);
- Student stu3 = new Student("千道流", 130);
- Student stu4 = new Student("波塞西", 200);
- Student stu5 = new Student("唐三", 25);
-
- set.add(stu1);
- set.add(stu2);
- set.add(stu3);
- set.add(stu4);
- System.out.println(set.add(stu5));
-
- System.out.println(set);
-
- }
-
- 输出内容:
- false
- [Student{name='唐三', age=25}, Student{name='比比东', age=50}, Student{name='千道流', age=130}, Student{name='波塞西', age=200}]
原文链接:https://blog.csdn.net/b15735105314/article/details/117248630
作者:以天使的名义
链接:http://www.javaheidong.com/blog/article/207646/320f5f7bb83d47ac98d6/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!