Set接口
无序不可重复。
无序: 添加顺序与抓取出来的顺序不一致
实现类HashSet
特点: 底层哈希表, 存取速度快
原理:
①添加元素时,首先调用hashCode方法以确认该元素要存到哪个位置
②如果目标位置已经有元素,就调用equals方法判断是否相同,如果相同就不允许加入,如果不同就允许加入。(一个位置存放多个元素)
class Poker{
String color;
int num;
public Poker(String color, int num){
this.num = num;
this.color=color;
}
public String toString(){
return this.color+" "+this.num;
}
public int hashCode(){
System.out.println("因为要确认"+this+"的位置,hasCode调用了!!");
return this.num;
}
public boolean equals(Object obj){
System.out.println("因为添加"+this+"时位置被占了!,调用equals方法看是否一致");
Poker p =(Poker)obj;
return this.num==p.num;
}
}
public class eee {
public static void main(String[] args) {
HashSet s = new HashSet();
s.add(new Poker("方块",13));
s.add(new Poker("红桃",5));
s.add(new Poker("黑桃",12));
s.add(new Poker("红桃",5));
System.out.println(s);
}
}
因为要确认方块 13的位置,hasCode调用了!!
因为要确认红桃 5的位置,hasCode调用了!!
因为要确认黑桃 12的位置,hasCode调用了!!
因为要确认红桃 5的位置,hasCode调用了!!
因为添加红桃 5时位置被占了!,调用equals方法看是否一致
[红桃 5, 黑桃 12, 方块 13]
实现类TreeSet
底层用红黑树(二叉树)实现!!!
特点: 如果元素具备自然顺序的特性,则会按自然顺序的特性进行排序存储
自然顺序: 字母, 数字都可以直接排序,如果没有可比性的元素加入,就会报错。
如何解决这个问题??
①实现Comparable接口,重写int compareTO方法!!!!!!!!!!!
②给TreeSet添加比较器Comparator!!!,即自定义一个类实现Comparator接口,重写Compare方法!!然后创建TreeSet的时候当参数传入!!
Comparable接口!!!:::‘
既然可比性用的是compareTo方法,所以判断是否重复也是用的compareTo方法!!!,于是相等的就加不进来!!
还是同样的例子!!!
class Poker implements Comparable{
String color;
int num;
public Poker(String color, int num){
this.num = num;
this.color=color;
}
public String toString(){
return this.color+" "+this.num;
}
public int hashCode(){
System.out.println("因为要确认"+this+"的位置,hasCode调用了!!");
return this.num;
}
public boolean equals(Object obj){
System.out.println("因为添加"+this+"时位置被占了!,调用equals方法看是否一致");
Poker p =(Poker)obj;
return this.num==p.num;
}
@Override
public int compareTo(Object o) {
System.out.println("因为要加入"+this+"调用了compareTo方法!!");
Poker p =(Poker)o;
return this.num-p.num;
}
}
public class eee {
public static void main(String[] args) {
TreeSet s = new TreeSet();
s.add(new Poker("方块",13));
s.add(new Poker("红桃",5));
s.add(new Poker("黑桃",12));
s.add(new Poker("红桃",5));
System.out.println(s);
}
}
结果如此、!!通过各个元素调用compareTo方法的次数可以判断底层是二叉树!!!!!! 所以不依赖hashCode和equals方法!!!!!
另外注意: 如果三个节点构不成一个二叉,就会自动调整平衡!!!!,所以实际上比较次序是与二叉平衡树有关!!!
因为要加入方块 13调用了compareTo方法!!
因为要加入红桃 5调用了compareTo方法!!
因为要加入黑桃 12调用了compareTo方法!!
因为要加入黑桃 12调用了compareTo方法!!
因为要加入红桃 5调用了compareTo方法!!
因为要加入红桃 5调用了compareTo方法!!
[红桃 5, 黑桃 12, 方块 13]
②给TreeSet添加比较器Comparator!!!,即自定义一个类实现Comparator接口,重写Compare方法!!然后创建TreeSet的时候当参数传入!!
class MyComparator implements Comparator{
public int compare(Object o1, Object o2) {
System.out.println("添加"+o1+"和"+o2+"比较的时候用了我呀");
Poker e1 = (Poker) o1;
Poker e2 = (Poker) o2;
return e1.num - e2.num;
}
}
class Poker implements Comparable{
String color;
int num;
public Poker(String color, int num){
this.num = num;
this.color=color;
}
public String toString(){
return this.color+" "+this.num;
}
public int hashCode(){
System.out.println("因为要确认"+this+"的位置,hasCode调用了!!");
return this.num;
}
public boolean equals(Object obj){
System.out.println("因为添加"+this+"时位置被占了!,调用equals方法看是否一致");
Poker p =(Poker)obj;
return this.num==p.num;
}
@Override
public int compareTo(Object o) {
System.out.println("因为要加入"+this+"调用了compareTo方法!!");
Poker p =(Poker)o;
return this.num-p.num;
}
}
public class eee {
public static void main(String[] args) {
MyComparator m = new MyComparator();
TreeSet s = new TreeSet(m);
s.add(new Poker("方块",13));
s.add(new Poker("红桃",5));
s.add(new Poker("黑桃",12));
s.add(new Poker("红桃",5));
System.out.println(s);
}
}
结果如下
添加方块 13和方块 13比较的时候用了我呀
添加红桃 5和方块 13比较的时候用了我呀
添加黑桃 12和方块 13比较的时候用了我呀
添加黑桃 12和红桃 5比较的时候用了我呀
添加红桃 5和黑桃 12比较的时候用了我呀
添加红桃 5和红桃 5比较的时候用了我呀
[红桃 5, 黑桃 12, 方块 13]
当元素有自然顺序 ,且TreeSet也有比较器。则优先考虑比较器!!
总结:
treeSet要注意的事项:
1. 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。
2. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素
的比较规则定义在compareTo(T o)方法上。
3. 如果比较元素的时候,compareTo方法返回 的是0,那么该元素就被视为重复元素,不允许添加.(注意:TreeSet与HashCode、equals方法是没有任何关系。)
4. 往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序 的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个
比较器。
5. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口, 在创建TreeSet对象的时候也传入了比较器
那么是以比较器的比较规则优先使用。