java 中的Set集合是无序的,并且其中不能包含重复的元素。这里的序是指,存入的顺序和取出的顺序是否一致,如果一致则为有序否则则为无序。
Set接口主要是实现类有三个,HashSet,TreeSet和EnumSet。
在HashSet中,哈希值是一个很重要的概念,下面通过例子说明:
class AA{
}
public class HashCodeDemo_02 {
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new AA());
hs.add(new AA());
hs.add(new AA());
hs.add(new AA());
System.out.println(hs);
}
}
输出为:
java集合框架学习.AA@8071a97
java集合框架学习.AA@55fe910c
java集合框架学习.AA@a62b39f
java集合框架学习.AA@3be4d6ef
@后面的就是hash值。
在java中,
HashSet中的每一个元素在存储的时候,都是用hashCode来计算它的存储位置。
当需要查询集合中的某个元素的时候,hash算法可以直接根据该元素的hashCode计算出该元素的存储位置,可以类比数据按下表存取。
HashSet中每个能存储元素的槽位通常称为桶,如果多个元素的hashCode值相同,但是通过equals方法比较又返回false,则就需要在一个桶里放多个元素,导致HashSet性能下降。这种情况要尽量避免。
举一个例子:
import java.util.HashSet;
class A{
public boolean equals(Object obj){
return true;
}
}
class B{
public int hashCode(){
return 1;
}
}
class C{
public boolean equals(Object obj){
return true;
}
public int hashCode(){
return 2;
}
}
public class HashSetDemo1 {
public static void main(String[] args){
HashSet hs = new HashSet();
hs.add(new A());
hs.add(new A());
hs.add(new B());
hs.add(new C());
hs.add(new C());
Iterator it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
运行结果如下:
java集合框架学习.B@1
java集合框架学习.C@2
java集合框架学习.A@2cdb03a1
java集合框架学习.A@3be4d6ef
一般在自定义类中,如果重写equals方法,对应的也会重写hashCode方法。
在存入一个新对象保证唯一性的时候,hashCode方法和equals方法的调用情况为:
如果hashCode一样,调用equals方法,如果equals返回false,元素不同可以存储。
如果hashCode不一样,不调用equals方法进行比较。
所以,高效的hashCode,才能保证高效的HashSet。
同样的,LinkedHashSet也是根据hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序。也就是说,当遍历LinkedHashSet时,将会按照元素的添加顺序访问集合里的元素。同样,LinkedHashSet也不存在相同的元素。
示例如下:
import java.util.LinkedHashSet;
public class LinkedHashSetDemo {
public static void main(String[] args){
LinkedHashSet lhs = new LinkedHashSet();
lhs.add("zhang");
lhs.add("wang");
lhs.add("li");
System.out.println(lhs);
lhs.remove("zhang");
lhs.add("zhang");
System.out.println(lhs);
}
} import java.util.LinkedHashSet;
public class LinkedHashSetDemo {
public static void main(String[] args){
LinkedHashSet lhs = new LinkedHashSet();
lhs.add("zhang");
lhs.add("wang");
lhs.add("li");
System.out.println(lhs);
lhs.remove("zhang");
lhs.add("zhang");
System.out.println(lhs);
}
}
输出为:
[zhang, wang, li]
[wang, li, zhang]