目录
day16笔记
一、HashSet
1. 存储特点
以hashCode排序,不能出现重复元素,相对无序(与输入顺序不相关)
2. 比较规则
首先比较hashCode,相同时调用当前对象的equals方法
- 如果hashCode相同,equals方法比较不相同,则存储地址发生冲突,顺次后延
- 如果hashCode相同,equals方法比较相同则为相同元素,不会添加
- 如果hashCode不同,认定是不同对象,不会调用equals方法比较
3. 哈希结构
- 在Object中调用native声明的方法计算出一个与内存地址相关的编码
- 可以在Object的子类中(所有类)重写hashCode方法
- 通常重写hashCode时将其转换为和对象属性值相关的计算公式
- 默认的hashCode计算方式使用31作为运算基数主要是出于性能的考虑
二、TreeSet
1. 存储特点
以元素之间的比较结果决定存放的顺序,不能出现重复元素,默认按照自然升序
2. 比较规则
可以盛放实现了自然排序接口的实例,如:基本数据类型包装类,字符串,自定义类型等
当一个TreeSet集合中出现不同类型的元素时,即泛型约束不强烈时,对于每一种类型均要实现自然排序接口,在重写的方法中指定不同类型比较时的结果,例如使用instanceof关键字判断比较对象的实例类型
Student student = null; // 1.判断实例的类型 if (o instanceof Student) { student = (Student) o; }else { // 如果待比较元素不是Student类型,不予添加 return 0; }
由于无法改写字符串及包装类中的compareTo方法,所以应避免在TreeSet集合中存入不兼容类型的数据
compareTo方法中,使用this关键字代表当前存入集合中的对象,参数列表中的对象为集合中已存在的对象,在得出最终比较结果时可能会发生多次比较
基于二分法的比较规则,逐渐缩小所在元素应在区间
返回0代表标记当前元素为重复元素,不会存入集合
返回正数代表当前元素所处位置应在当前比较元素之后
返回负数代表当前元素所处位置应在当前比较元素之前
3.几个方法
TreeSet<Integer> treeSet = new TreeSet<>();
// 排序的时间:添加元素时,通过元素本身值的比较决定相应的属性,compareTo()方法调用
treeSet.add(50);
treeSet.add(30);
treeSet.add(100);
treeSet.add(20);
// 输出 20 30 50 100
// treeSet.headSet()
// 第一个参数为指定的比较基准,不需要是集合中的元素(不包括参数这个元素)
for (Integer integer : treeSet.headSet(55)) {
System.out.println(integer); // 20 30 50 (55之前的元素)
}
// treeSet.tailSet(比较的范围,是否包含-true)
// 第一个参数为指定的比较基准,不需要是集合中的元素(包括参数这个元素)
for (Integer integer : treeSet.tailSet(80)) {
System.out.println(integer);// 100 (80之后的元素)
}
// treeSet.subSet(起始值,是否包含-true,终止值,是否包含-false)
// 第一个参数为指定的比较基准,不需要是集合中的元素
for (Integer integer : treeSet.subSet(20, 40)) {
System.out.println(integer);//20 30 (左闭右开)
}
三、比较器
1. Comparable
自然排序接口,重写compareTo方法,使用方法见TreeSet
// 1.实现comparable方法
public class Student implements Comparable<Student>{}
// 2.重写compareTo方法
@Override
public int compareTo(Student o) {}
//return 0 相同元素不存进去
//return 1;// 正数放后
//return -1;// 负数放前
2. Comparator
外部排序接口,使用匿名内部类的方式实现,指定泛型,并重写compare(paraA,paraB)方法
// 匿名内部类 -> 只能使用一次,不需要更改类本身的结构,比较规则有变动的情况
// 当同时具有Comparable和Comparator时,以Comparator规则为准
Set<Person> set = new TreeSet<>(new Comparator<Person>() {
// 需求:向TreeSet集合当中存放Student对象,使得对象之间根据年龄升序
@Override
public int compare(Person newPerson, Person oldPerson) {
// 第一个参数为新添加进来的对象,第二个参数为集合当中与之比较的对象
// 当两个对象属性完全相同时,认定是重复对象,返回0
if (newPerson.getName().equals(oldPerson.getName()) && newPerson.getAge() == oldPerson.getAge()) {
// 当两个比较对象各属性相同时,认定相同,不予添加
return 0;
}
// 2.年龄的比较
if (newPerson.getAge() >= oldPerson.getAge()) {
// 通过正负来决定位置
// 正数放后
// 负数放前
return 1;
} else {
return -1;
}
}
});
- paraA代表当前正在存入的元素
- paraB代表集合中已存在的元素,有可能发生多次比较
- 返回0代表标记当前元素为重复元素,不会存入集合
- 返回正数代表当前元素所处位置应在当前比较元素之后
- 返回负数代表当前元素所处位置应在当前比较元素之前