问题描述
说我想在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 ? e2==null : 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;
}
这里map
是HashMap
的一个实例,因此我们应该看一下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);
}
}