今天想要进行实体类集合,结果我list强制转型set报错了,然后我new HashSet<>(list);
这个虽然没报错,但是这个却没有实现去重。
有懂底层的能科普么?
HashSet的底层其实是封装了HashMap,而 new HashSet<>(list)
底层就是调用了addAll 方法
addAll 底层调用了add 方法,add 又调用了HashMap的 put(key,val) 方法
HashMap 底层是数组+链表的结构
其中如何判断map 中是否已经有值也就是所谓的去重 判断方法如下
判断是否相等的逻辑如下:
p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k)))
也就是说,重写了hashCode 和 equals 能实现去重,如果没有重写 equals ,只能 实现是同一个对象的去重,
举个栗子
class A{
String name;
public A(String name){
this.name = name;
}
}
不重写equals的话,
A a = new A("wu");
A b = new A("wu");
在 HashMap中 哪怕 a和b的hashCode值相等
但是 后续判断 a ==b 为false,因为a 和b的地址并不一样,
a.equals(b) 也是false,因为没有重写 equals,那么该方法继承自 Object
方法定义如下:
public boolean equals(Object obj) {
return (this == obj);
}
其实还是判断地址是否一致
jdk8 源码截图
首先hashset是用hashmap实现得,jdk8中的hashmap是数组+链表,此时你set的add其实就是map的put方法了,截图是map的put方法,几个圈中间的for是循环整个链表中的所有key,找到key相同的时候,e就不为null了
他在判断key是否相同时,主要就是那几个判断,所以你重写以后,数据一致就会认为你是重复key