赞
踩
Set系列集合
Set集合的实现类
HashSet:无序、无索引、不重复
LinkedHashSet:有序、不重复、无索引
TreeSet:可排序、不重复、无索引
Set系列集合没有特有的方法,直接继承顶层接口Collection中的所有方法并使用。
1.HashSet
HashSet底层:
哈希表的组成:
HashSet底层存储数据:
通过调用hashCode方法计算对象的哈希值,然后根据哈希值和数组长度计算出对象应存入哈希表的位置,然后该对象再调用equals方法和当前位置的所有对象依次比较,若存在相同属性值对象,则舍弃该对象不存,若不存在属性值相同对象,则将该对象存入当前位置。
注意:一定要重写hashCode和equals方法,这样才能保证实现不重复
哈希值细节:
HashSet底层原理:
JDK8以后,当链表长度超过8且数组长度大于等于64时,自动转换为红黑树
如果集合中存储的是自定义对象,必须重写hashCode和equals方法
三个问题:
HashSet为什么存和取的顺序不一样?
HashSet为什么没有索引?
HashSet是利用什么机制保证数据去重的?
2.LinkedHashSet
总结:
1.LinkedHashSet集合的特点和原理是怎样的?
2.以后如果要数据去重,我们应该使用哪个?
3.TreeSet
TreeSet的特点:
TreeSet集合默认规则
- public class TreeSetDemo1 {
- public static void main(String[] args) {
- //创建TreeSet集合对象
- TreeSet<Integer> ts = new TreeSet<>();
- //添加元素
- ts.add(5);
- ts.add(3);
- ts.add(1);
- ts.add(4);
- ts.add(2);
-
- //打印集合
- System.out.println(ts);//[1, 2, 3, 4, 5]
-
- //三种通用遍历方式遍历
- //迭代器遍历
- /*Iterator<Integer> it = ts.iterator();
- while (it.hasNext()){
- int i = it.next();
- System.out.println(i);
- }*/
-
- //增强for遍历
- /*for (Integer t : ts) {
- System.out.println(t);
- }*/
-
- //lambda表达式遍历
- ts.forEach(i-> System.out.println(i));
- }
- }
TreeSet两种比较方式
方式一:
默认排序/自然排序:Javabean类实现Comparable接口指定比较规则
举例:学生有姓名、年龄属性,现要求按照学生的年龄进行排序,同年龄按照姓名字母排序
- public class Student2 implements Comparable<Student2>{
- //通过compareTo方法指定比较规则
-
- //this:表示当前要添加的元素
- //o:表示已经在红黑树中存在的元素
-
- //返回值:
- //正数:表示当前要添加的元素是大的,存右边
- //负数:表示当前要添加的元素是小的,存左边
- //0:表示当前要添加的元素已经存在,舍弃
- @Override
- public int compareTo(Student2 o) {
- //指定排序规则
- //按照年龄升序进行排列
- return this.getAge() - o.getAge();
- }
- }
- public class TreeSetDemo2 {
- public static void main(String[] args) {
- Student2 s1 = new Student2("zhangsan",23);
- Student2 s2 = new Student2("lisi",24);
- Student2 s3 = new Student2("wangwu",25);
-
- TreeSet<Student2> ts = new TreeSet<>();
-
- ts.add(s1);
- ts.add(s2);
- ts.add(s3);
-
- System.out.println(ts);
- }
- }
方式二:
比较器排序:创建TreeSet对象时,传递比较器Comparator指定规则
举例:存入字符串"b","ac","bc","abc",按照长度排序,如果一样长则按照首字母排序
- public class TreeSetDemo3 {
- public static void main(String[] args) {
-
- /*TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
- @Override
- public int compare(String o1, String o2) {
- int i = o1.length() - o2.length();
- i = i == 0 ? o1.compareTo(o2) : i;
- return i;
- }
- });*/
-
- //o1:表示当前要添加的元素
- //o2:表示在红黑树中已经存在的元素
- TreeSet<String> ts = new TreeSet<>((o1,o2)->{
- //按照长度排序
- int i = o1.length() - o2.length();
- //如果长度一样按照首字母排序
- i = i == 0 ? o1.compareTo(o2) : i;
- return i;
- });
-
- ts.add("c");
- ts.add("ac");
- ts.add("bc");
- ts.add("abc");
-
- System.out.println(ts);
- }
- }
使用原则:默认使用第一种,如果第一种不能满足当前需求,就使用第二种
总结:
1.如果想要集合中的元素可重复
2.如果想要集合中的元素可重复,而且当前的增删操作明显多于查询
3.如果想对集合中的元素去重
4.如果想对集合中的元素去重,而且保证存取有序
5.如果想对集合中的元素进行排序
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。