Q.1)如AbstractSet文档中所述-“此类不会覆盖AbstractCollection类的任何实现。”如果它不覆盖或更改add(Object o)或由Collection类实现的任何其他AbstractCollection接口协定,则仅继承它们,如HashSet

HashSet和其他Set对象如何执行规定,例如没有重复的添加检查或插入元素的哈希表方式,这与List或其他Collection对象可以添加元素的方式完全不同。

Q.2)在文档中,对于AbstractSet,它是这样编写的,AbstractSet仅添加了equalshashcode的实现。但是,在方法详细信息部分中,提到Object类已经重写了equalshashcode方法。 AbstractSet仅继承而不对这两个方法做任何更改吗?如果是这样,AbstractSet类的重要性是什么?请澄清

最佳答案

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值从不实际使用或检索,但它允许我们使用此后备映射来验证项目是否存在于Set中。

如果我们提供的值在地图中不存在,则对map.put()的调用会将该项放置在地图中并返回我们的对象。否则,映射保持不变,并且该方法返回null。 HashMap在这里为HashSet做艰苦的工作。

这与AbstractCollection类提供的实现不同,因此需要重写。

Q2:AbstractSet对equals()和hashCode()的使用

我认为您在某种程度上误解了AbstractSet在做什么。 AbstractSet的目的是提供等于和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方法。

10-04 13:03