为了账号安全,请及时绑定邮箱和手机立即绑定

Set 接口如何强制执行无重复添加和不保留插入顺序规定

Set 接口如何强制执行无重复添加和不保留插入顺序规定

手掌心 2023-04-13 14:51:22
Q.1) 正如AbstractSet的文档中所写——“此类不会覆盖该类的任何实现AbstractCollection。” 如果它不覆盖或更改 add(Object o)或由类实现的任何其他Collection接口协定AbstractCollection,而只是继承它们等HashSet。How doHashSet和 other Setobjects 然后强制执行诸如不重复添加检查或插入元素的 Hashtable 方式等规定,List这与or other objects 可以添加元素的方式完全不同Collection。Q.2)在文档中,对于AbstractSet,它是写的,只是添加了和 的AbstractSet实现。但是,在方法细节部分,提到了类已经覆盖了方法。是否只继承而不对这两个方法做任何改变?如果是这样,类的重要性是什么?请澄清equalshashcodeObjectequalshashcodeAbstractSetAbstractSet
查看完整描述

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 方法。


查看完整回答
反对 回复 2023-04-13
?
梦里花落0921

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 方法。


查看完整回答
反对 回复 2023-04-13
  • 2 回答
  • 0 关注
  • 108 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信