HashSet是Set接口的实现,所以不包含相同元素。HashSet是基于Hash算法的集合,具有很好的查找和存取性能。HashSet不能保证输出的顺序和插入的顺序一样。
import java.util.HashSet; import java.util.Iterator; public class hashset { public static void main(String[] args) { HashSet<String> set = new HashSet<String>(); set.add("abc"); set.add("acd"); set.add("bcd"); boolean b = set.add("abc"); System.out.println("abc元素是否再次添加成功:"+b); Iterator<String> it = set.iterator(); while(it.hasNext()){ String s = it.next(); System.out.println(s); } } }
上面程序的运行结果:
abc元素是否再次添加成功:false bcd abc acd
通过程序的运行结果可以看出当再次插入“abc”时是没有插入成功的,说明HashSet集合是不允许元素重复的,同时他们的输出顺序也不一定是加入HashSet集合的顺序。
当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet中的存储位置。如果两个元素的equals()方法的返回值等于true,但他们的hashCode()方法的返回值不一样,它们都将存在HashSet不同位置中。如果两个元素返回的equals()方法的值和hashCode()方法的值都相等,则说明这两个元素相等,新增加的元素不会被加入。
import java.util.HashSet; class A{ private String name; public A(String name){ this.name = name; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof A) { A stu = (A) obj; return this.name.equals(stu.name); } return false; } @Override public String toString() { return name; } } class B{ private String name; public B(String name){ this.name = name; } @Override public int hashCode() { return name.hashCode(); } @Override public String toString() { return name; } } class C{ private String name; public C(String name){ this.name = name; } public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof C) { C stu = (C) obj; return this.name.equals(stu.name); } return false; } @Override public int hashCode() { return name.hashCode(); } @Override public String toString() { return name; } } public class hashset { public static void main(String[] args) { HashSet<A> setA = new HashSet<A>(); setA.add(new A("张三")); setA.add(new A("张三")); System.out.println(setA); HashSet<B> setB = new HashSet<B>(); setB.add(new B("李四")); setB.add(new B("李四")); System.out.println(setB); HashSet<C> setC = new HashSet<C>(); setC.add(new C("王五")); setC.add(new C("王五")); System.out.println(setC); } }
上面程序的运行结果:
[张三, 张三] [李四, 李四] [王五]
上面程序中分别将两个相同A、B、C对象加入到对应的A、B、C类型的HashSet集合中。其中A类只重写了equals()方法和toString()方法,B类只重写了hashCode()方法和toString()方法,C类重写了equals()方法、hashCode()方法和toString()方法。
从结果可以看出,即使两个A对象通过equals()方法比较的值相等,但hashCode值不同,HashSet把它们当做了两个对象加入其中。两个B对象的hashCode值相同,但它们的equals()方法返回值为false,所以HashSet把它们当做了两个对象加入其中。因为两个方法都重写了,两个C对象的equals()方法比较的值相等,hashCode值也相同,所以HashSet把它们当成一个对象加入其中。
总结:当把一个对象加入到HashSet中时,不仅要重写该类的equals()方法,同时也要重写该类的hashCode()方法,这样才能保证HashSet中的对象没有重复。