关于Set集合
它类似一个罐子,不能记住元素的添加顺序,它类似Collection,只是他不允许包含重复元素
去重复数据,我只需要把所有的数据都添加进Set,Set会自动把重复的数据去掉。如果把重复数据添加到Set中
add方法会false,同时并不会添加进去。
(什么时候用Set呢?
去重复数据,我只需要把所有的数据都添加进Set,Set会自动把重复的数据去掉。
请问你用map实现起来有这么快捷吗?
在查找数据时,我只要知道数据的key,我一次就能拿到这个数据。你用Set又行么?)
Set子类又有Hashset,TreeSet,EnumSet等
①HashSet:是Set接口的典型实现类,大多数用Set时候都用这个类,用Hash算法来存储集合元素(hash算法克制根据元素的hashcode值来快速定位元素),有较好的存储和查找性能
1.不能保证元素顺序,与添加顺序无关
2.不是同步,多线程修改集合时,需要通过代码保证同步
3.元素值可以是null
HS存储一个元素时候,会调用HashCode方法来得到该对象的HashCode值,根据此值来确定存储位置。
两个元素equals()比较为true时候,同事hashcode()方法返回值不相等,HS仍然会将两个添加成功
例如
//只重写了equals方法,但是hashcode()肯定会不等,所以会添加成功 class A { @Override public boolean equals(Object obj) { // TODO Auto-generated method stub return true; } } //只重写了Hashcode方法 class B { public int hashCode() { return 1; }; } class C { @Override public int hashCode() { return 2; } public boolean equals(Object obj) { return true; }; } public class HashSetTest { public static void main(String[]args) { HashSet set=new HashSet<>(); set.add(new A()); set.add(new A()); set.add(new B()); set.add(new B()); set.add(new C()); set.add(new C()); System.out.println(set); } }
[vczx.A@2d11f5f1, vczx.B@1, vczx.B@1, vczx.C@2, vczx.A@5994a1e9]
HashSet中每个能存储元素的“槽位”通常称之为“桶”,例如上面例子的B类,hashcode返回相同,但是equals不同,所以,它就会在一个桶里面占两个元素,这样就会导致性能下降。
两个A,B,一个C
因为C equals总是返回true,hashcode总是返回2.所以add方法根据不重复原则就会只添加第一个。
所以实际应用中如果用HashSet集合时候,如果对象重写了equals方法,则也应该同时重写hashcode()方法,要不然add会两个都添加,这样就会违背使用Set的初心了