java中使用HashSet去重必须重写hashCode()和equals()。
但是HashSet去重并不会把原来的给覆盖掉,而是直接丢弃新的。
例如有一个类:
public class BaseEntity implements Serializable {
private String id;
private String name;
// ...... 演示不写get set toString 方法和构造器
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BaseEntity)) return false;
BaseEntity that = (BaseEntity) o;
return Objects.equals(getId(), that.getId());
}
@Override
public int hashCode() {
return Objects.hash(getId());
}
}
在写一个main方法:
public static void main(String[] args) {
Set<BaseEntity> baseEntitySet = new HashSet<>();
BaseEntity baseEntity1 = new BaseEntity("id=1", "张三");
BaseEntity baseEntity2 = new BaseEntity("id=2", "李四");
BaseEntity baseEntity3 = new BaseEntity("id=1", "王五");
baseEntitySet.add(baseEntity1);
baseEntitySet.add(baseEntity2);
baseEntitySet.add(baseEntity3);
for(BaseEntity item : baseEntitySet){
System.out.println(item);
}
}
然后会得到如下结果:
BaseEntity{id='id=2', name='李四'}
BaseEntity{id='id=1', name='张三'}
我们就会发现name="王五"的对象并没有覆盖name="张三"的对象。
原因是因为HashSet底层使用的是HashMap。
当调用add()时,会把对象存入key中,value则为一个静态的Object对象。
源码如下:
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
但是HasHMap遇到重复的key时只会把value替换掉。
而HashSet存进去的对象是放在HashMap中的key里。
所以使用HasHSet去重得到的是第一个未重复对象,后续重复的对象直接被丢弃。没有被覆盖。