分析 HashSet 和 TreeSet 分别如何实现去重的:
(1)HashSet 的去重机制:hashCode() + equals()。底层先通过存入对象,进行运算得到一个 hash 值,通过 hash 值得到对应的索引,如果发现 table 索引所在的位置,没有数据,就直接存放;如果有数据,就进行 equals 遍历比较,比较后不相同,就加入,否则,不加入。
(2)HashMap 的去重机制:如果传入了一个 Comparator 匿名对象,就使用实现的 compare 去重。如果方法返回0,就认为是相同的元素,不添加键,把对应的值覆盖;如果没有传入 Comparator 匿名对象,则以所添加的对象实现的 Compareable 接口的 CompareTo 去重。
附1:三种方法的对比
① equals
这个方法只能用作对象之间的比较,比较是否相等(=/ !=),而不能比较出谁大谁小(>,<,=)。
如果没有重写equals方法,那会自动调用object类的equals方法,即比较地址。
② 基于 Comparble 接口类的比较
写在类的里面,参数是所要比较的类。比较本类和所传入的类。
对用用户自定义类型,如果要想按照大小与方式进行比较时:在定义类时,实现Comparble
接口即可,然后在类中重写 compareTo 方法。这种方式可以实现存在排序的大小比较,但是只能根据一个比较准则来进行比较。
class Student implements Comparable<Student> { public int age; public String name; @Override public int compareTo(Student o) { // 写在类的里面,比较的是本类和传入的类 return this.age - o.age; } }
③ 基于 Comparator 接口类的比较
写在类的外部,参数是两个比较的对象。
重写 Comparetor 里的 compare 方法即可。可以每个准则对应生成一个类、实现 Comparator 接口,然后重写 compare 方法。
class Student { public int age; public String name; } // 写在类的外部,参数是两个比较的对象 //年龄比较器 class AgeComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.age - o2.age; } } //姓名比较器 class NameComparator implements Comparator<Student> { @Override public int compare(Student o1, Student o2) { return o1.name.compareTo(o2.name);//直接调用引用类型String的比较方法 } }
附2:代码分析题:下面代码运行是否抛出异常,从源码层面说明原因。
TreeSet treeSet = new TreeSet(); treeSet.add(new Person()); class Person{}
标签:分析,Comparator,HashSet,age,比较,Student,public,TreeSet From: https://www.cnblogs.com/97gogo/p/18383205分析:add 方法,因为 TreeSet() 构造器没有传入 Comparator 接口的匿名内部类,所以在底层会实现 Comparable<? super K> k = (Comparable<? super K>) key; 即把 Person 类转成 Compareable 类型,而 Person 类并未实现该接口。因此 add 语句会报错:ClassCastException。