set 集合是顶级集合接口Collection的一个继承接口,有两个实现类HashSet、TreeSet
HashSet:无序(输出顺序与输入顺序不同)而且不可重复;
重点讲一下不可重复,因为HashSet底层数据结构基于哈希表(散列表),哈希表存入的方式是键值对,键是不可以重复的。
如何判断哈希值是否重复呢?
实体类需要重写HashCode方法和equals方法
(“equals定义在Object中,没有重写的情况下equals比较的是内存地址“)
/**重写hashCode方法
* 返回当前对象的哈希值(等于它的年龄)
*/
@Override
public int hashCode() {
return this.age;
}
/**重写equals方法
*只要名字相同,则认为是同一个对象,则返回真,反之
*/
@Override
public boolean equals(Object obj) {
Dog d=(Dog)obj;
if(this.name.contentEquals(d.name)) {
return true;
}
return false;
}
结论: 先判断hash值在当前的集合中是否存在了,如果没有,直接添加,如果存在相同的hash值,再调用equals判断,若比较结果返回true就不会存入集合当中。
TreeSet数据结构基于二叉树,特征为有序
TreeSet是有序的吗?无序:插入顺序与取出顺序; 有序:数据再内部会排序
二叉树的概念:左边的树的键值小于根的键值,右边树的键值大于根的键值
TreeSet又有俩种排序方法:自然排序和选择器排序
当自定义的Dog类重写Comparable接口里的方法后,在方法中只有一个条件时输出集合只会有一个对象,如按年龄从小到大输出,有相同年龄是只会输出一个
自然排序:里面的对象具备排序的方法;实现Comparable接口,
重写compareTo方法(比较对象)
/**比较对象(主条件age,次要条件name)
*根据年龄排序 从小到大
*/
@Override
public int compareTo(Object o) {
//如果年龄相同 比较名字
Dog d=(Dog)o;
int n=d.age-this.age;
//三种情况 >0 我大; =0 一样大; <0 我小
if(n==0) {//年龄相同
return this.name.compareTo(d.name);
}
return n;
}
没有实现接口是会报错的
选择器排序:里面的对象不具备排序的方法,所以给对象一个排序的选择器;实现Comparator接口;实例化TreeSet 传入一个排序器
package com;
import java.util.Comparator;
//Dog的帮助类 实现了Comparator接口
public class DogTools implements Comparator<Dog>{
@Override
public int compare(Dog o1, Dog o2) {
// TODO Auto-generated method stub
return o1.getAge()-o2.getAge();
}
}
重写的排序方法与自然排序重写后大同小异,只是在需要选择排序的时候需要实例化TreeSet 传入一个排序器
TreeSet<Dog> ts=new TreeSet<Dog>(new DogTools());
方法总结:选择器排序优先级>自然排序
朋友们可以去尝试尝试,欢迎留言...