Set集合
一 .Hashset
JDK8之前,哈希表 = 数组+链表
JDK8开始后,哈希表中引入了红黑树后,进一步提高了操作数据的性能。
JDK8开始,哈希表 = 数组+链表+红黑树
JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树
哈希表存储数据的详细流程
① 创建一个默认长度16,默认加载因为0.75的数组,数组名table
② 根据元素的哈希值跟数组的长度计算出应存入的位置
③ 判断当前位置是否为null,如果是null直接存入,如果位置不为null,表示有元素, 则调用equals方法比较属性值,如果一样,则不存,如果不一样,则存入数组。
④ 当数组存满到16*0.75=12时,就自动扩容,每次扩容成原先的两倍
目标:认识Set家族集合的特点。
创建一个Set集合,特点:无序,不重复,无索引。
Set<String> set = new HashSet<>(); // 一行经典代码 HashSet 无序,不重复,无索引。
/*哈希值:对象的整数表现形式1. 如果没有重写hashCode方法,不同对象计算出的哈希值是不同的2. 如果已经重写hashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的3. 但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)*/
TreeSet
public class TreeSetDemo{public static void main(String[] args) {// 目标:搞清楚TreeSet集合对于自定义对象的排序Set<Teacher> teachers = new TreeSet<>(new Comparator<Teacher>() {@Overridepublic int compare(Teacher o1, Teacher o2) {// 按年龄降序// return o2.getAge() - o1.getAge();// 按薪水比较(手动实现)if (o1.getSalary() > o2.getSalary()) {return 1;} else if (o1.getSalary() < o2.getSalary()) {return -1;}return 0;// 按薪水比较(使用Double工具类)// return Double.compare(o1.getSalary(), o2.getSalary()); // 薪水升序// return Double.compare(o2.getSalary(), o1.getSalary()); // 薪水降序}}); // 排序,不重复,无索引// 简化形式(Lambda表达式)// Set<Teacher> teachers = new TreeSet<>((o1, o2) -> // Double.compare(o1.getSalary(), o2.getSalary())); // 排序,不重复,无索引teachers.add(new Teacher("老陈", 20, 6232.4));teachers.add(new Teacher("dlei", 18, 3999.5));teachers.add(new Teacher("老王", 22, 9999.9));teachers.add(new Teacher("老李", 20, 1999.9));System.out.println(teachers);// 结论:TreeSet集合默认不能给自定义对象排序,因为不知道大小规则。// 解决办法有两种:// 1、对象类实现Comparable比较接口,重写compareTo方法,指定大小比较规则// 2、使用TreeSet(Comparator c)构造方法,传入比较器器对象指定比较规则}
}
return this.getAge() - o.getAge(); // 升序return o.getAge() - this.getAge(); // 降序
结论
// 结论:TreeSet集合默认不能 给自定义对象排序啊,因为不知道大小规则。// 一定要能解决怎么办?两种方案。// 1、对象类实现一个Comparable比较接口,重写compareTo方法,指定大小比较规则// 2、public TreeSet(Comparator c)集合自带比较器Comparator对象,指定比较规则
Double.compare(double a, double b)
Double.compare(double a, double b)
是 Java 中 java.lang.Double
类提供的一个静态工具方法,用于比较两个 double
类型的值的大小,返回一个整数值表示比较结果:
- 如果
a > b
,返回 1 - 如果
a == b
,返回 0 - 如果
a < b
,返回 -1
在代码中的具体应用
在你的 TreeSet 比较器中:
Double.compare(o1.getSalary(), o2.getSalary())
- 当
o1
的薪水 >o2
的薪水时,返回 1 → TreeSet 会把o1
排在o2
后面 - 最终实现 薪水升序(从低到高)
- 当
Double.compare(o2.getSalary(), o1.getSalary())
- 当
o2
的薪水 >o1
的薪水时,返回 1 → TreeSet 会把o2
排在o1
后面(即o1
排在前面) - 最终实现 薪水降序(从高到低)
- 当
为什么用这个工具类?
简化代码:替代了手动写 if-else
比较的逻辑,让代码更简洁。
// 按薪水比较(手动实现)if (o1.getSalary() > o2.getSalary()) {return 1;} else if (o1.getSalary() < o2.getSalary()) {return -1;}
处理特殊值:double
类型存在 NaN
(非数字)等特殊值,Double.compare()
已经内部处理了这些特殊情况,避免了手动比较可能出现的逻辑漏洞。
一致性:作为 Java 标准库方法,确保了比较逻辑的规范性和一致性,减少出错概率。
类似的工具方法还有:
Integer.compare(int a, int b)
Long.compare(long a, long b)
Float.compare(float a, float b)