当我向HashSet中添加重复元素时会发生什么?旧元素是否被覆盖?

问题描述

说我想在HashSet添加重复的元素。我们知道这是不允许的。所以我碰到了2,比方说理论

在此link的'PROPERTIES,number 2'下,它表示:

HashSet不允许重复的元素。如果您尝试插入 重复的元素,较旧的元素将被覆盖

但是当我检查在IDE中提供的文档时,在方法add()中,它指出:

* If this set already contains the element,the call leaves the set
* unchanged and returns {@code false}.

那么它会覆盖(替换)旧元素,还是保留集合不变并返回false? :)我为他们说的相反而疯狂吗?

解决方法

IDE正在显示Set.add方法的官方规范(javadocs)的摘录。

IDE是正确的。相信官方文档,而不是一些“漂亮”的网站。


但是创建该网站的人又怎么会犯这么大的错误呢?

请始终记住,像您找到的网站这样的网站的主要动机是从页面浏览量中赚钱。他们通常更注重“搜索引擎优化”,而不是材料质量。


但是问题是那些“随机”站点有时会对某些概念做出“更漂亮”的解释。对于初学者来说,官方文档有时太难追踪了。

那么哪个更好?那些东西很容易阅读,但是错了吗?还是准确的东西?

在这种情况下,您不能说官方文件很难理解。您自己可以看到,从官方文档中获取的文字与第三方网站之间的矛盾。

我建议我们始终尝试首先阅读官方javadocs,并始终相信它比任何其他文献都早... ... 包括StackOverflow答案!唯一更具权威性的内容 1 是OpenJDK源代码。


1-甚至值得商bat。一方面,代码确定实际发生的情况。另一方面,代码可能会从一个版本更改为另一个版本。因此,依靠javadocs中未指定 的行为可能会导致可移植性问题。

,

通过查看源代码,可以验证任何理论。

例如,对于JDK 8,HashSet::add实现如下:

/**
     * Adds the specified element to this set if it is not already present.
     * More formally,adds the specified element <tt>e</tt> to this set if
     * this set contains no element <tt>e2</tt> such that
     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
     * If this set already contains the element,the call leaves the set
     * unchanged and returns <tt>false</tt>.
     *
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     * element
     */
    public boolean add(E e) {
        return map.put(e,PRESENT)==null;
    }

这里mapHashMap的一个实例,因此我们应该看一下HashMap::put

 /**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key,the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>,or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    public V put(K key,V value) {
        return putVal(hash(key),key,value,false,true);
    }

putVal的实现包含以下代码:

            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
,

执行下面的程序,您将看到不允许重复的元素:

import java.util.HashSet;

public class Test {
    public static class Dummy{
         String s1;
         String s2;
        public Dummy(String s1,String s2) {
            super();
            this.s1 = s1;
            this.s2 = s2;
        }
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((s1 == null) ? 0 : s1.hashCode());
            return result;
        }
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Dummy other = (Dummy) obj;
            if (s1 == null) {
                if (other.s1 != null)
                    return false;
            } else if (!s1.equals(other.s1))
                return false;
            return true;
        }
        @Override
        public String toString() {
            return "Dummy [s1=" + s1 + ",s2=" + s2 + "]";
        }
    }
    
    
    public static void main(String[] args) {
        HashSet<Object>hashSet =new HashSet<>();
        Object o1 = new Dummy("a","b");
        Object o2 = new Dummy("a","c");
        System.out.println(o1.equals(o2));
        hashSet.add(o1);
        System.out.println(hashSet);
        hashSet.add(o2);
        System.out.println(hashSet);
    }

}