2 回答
TA贡献1906条经验 获得超10个赞
Q1:HashSet 是如何强制重复检查的?
如果您查看java.util.HashSet中的实现,您将看到以下代码:-
private static final Object PRESENT = new Object();
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
发生的事情相当简单;我们使用一个私有的 HashMap 实例,它接受我们提供的值并将其作为 HashMap 的键插入。映射的PRESENT值从未实际使用或检索过,但它允许我们使用此支持映射来验证该项目是否存在于集合中。
如果地图中不存在我们提供的值,则调用map.put()会将项目放置在地图中并返回我们的对象。否则,地图保持不变并且该方法返回 null。HashMap 在这里为 HashSet 做着艰苦的工作。
这与AbstractCollection类提供的实现不同,因此需要重写。
Q2:AbstractSet对equals() & hashCode()的使用
我认为您稍微误解了 AbstractSet 在这里做什么。AbstractSet 的目的是提供 equals 和 hashCode 的集合安全实现。
相等检查是通过验证我们正在比较两个 Set 对象,它们具有相同的大小,并且它们包含相同的项目来执行的。
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
hashCode 是通过遍历 Set 实例并迭代地散列每个项目产生的:
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
任何从 AbstractSet 扩展的类都将使用 equals() 和 hashCode() 的这个实现,除非它明确地覆盖它们。此实现优先于java.lang.Object中定义的默认 equals 和 hashCode 方法。
TA贡献1772条经验 获得超5个赞
您提供的文档是针对 Java 7 的,我正在检查 Java 8 的代码,我发现了以下内容,所以我认为它与 Java 7 不一样,您仍然可以在文档时使用相同的方法检查代码对你来说不是很清楚: Q1: HashSet Overrides the add method in AbstractCollection 你可以很容易地检查这一点,如果你在某个IDE中打开HashSet代码。如果父母不重写某些方法并不意味着它的孩子不能这样做。
Q2:再次通过检查代码,我们注意到 AbstractSet 定义了它自己的 equals 和 hashCode 方法的实现。它还覆盖了 AbstractCollection 的 removeAll 方法。
添加回答
举报