java.util.Set 中的重复元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1642210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Duplicate elements in java.util.Set
提问by Neo
java.util.Set
implementations removes the duplicate elements.
java.util.Set
implementations 删除重复的元素。
How are duplicates elements deleted internally in a java.util.Set
??
如何在内部删除重复元素java.util.Set
?
回答by Tomas
Read your question more detailed:
更详细地阅读您的问题:
You can't add duplicates, from java doc for Set.add() or do you mean addAll?:
您不能从 Java 文档中为 Set.add() 添加重复项,还是您的意思是 addAll?:
Adds the specified element to this set if it is not already present (optional operation). More formally, adds the specified element e to this set if the set contains no element e2 such that (e==null ? e2==null : e.equals(e2)). If this set already contains the element, the call leaves the set unchanged and returns false. In combination with the restriction on constructors, this ensures that sets never contain duplicate elements.
如果指定的元素尚不存在,则将其添加到此集合中(可选操作)。更正式地,如果集合不包含元素 e2 使得 (e==null ? e2==null : e.equals(e2)),则将指定的元素 e 添加到该集合中。如果此集合已包含该元素,则调用将保持该集合不变并返回 false。结合对构造函数的限制,这确保了集合永远不会包含重复的元素。
回答by jitter
Actually AFAIK from the sources most Set
implementations in java don't even check if the element is already contained.
实际上,来自Set
Java 中大多数实现的源代码中的 AFAIK甚至不检查该元素是否已包含。
They just always execute the add()
on their internal structure which holds the set elements and let that object handle the duplication case.
他们只是总是add()
在保存集合元素的内部结构上执行 ,并让该对象处理重复情况。
e.g. HashSet
calls put(K,V)
on the internal HashMap
which just inserts the new object overwriting the old entry if duplicate.
例如,HashSet
要求put(K,V)
对内部HashMap
只是插入新的对象覆盖旧的条目;如果不重复。
回答by Nick Holt
Reading a little into your question I'm guessing that you're seeing strange behaviour with a java.util.HashSet
(typically what everyone uses by default).
稍微读一下你的问题,我猜你看到了奇怪的行为java.util.HashSet
(通常是默认情况下每个人都使用的)。
Contary to the contract of java.util.Set
it is possible to get the same object in a java.util.HashSet
twice like this:
与合同相反,java.util.Set
可以java.util.HashSet
像这样在两次中获得相同的对象:
import java.util.HashSet;
import java.util.Set;
public class SetTest
{
public static void main(String[] args)
{
MyClass myObject = new MyClass(1, "testing 1 2 3");
Set<MyClass> set = new HashSet<MyClass>();
set.add(myObject);
myObject.setHashCode(2);
set.add(myObject);
System.out.println(set.size()); // this will print 2.
}
private static class MyClass
{
private int hashCode;
private String otherField;
public MyClass(int hashCode, String otherField)
{
this.hashCode = hashCode;
this.otherField = otherField;
}
public void setHashCode(int hashCode)
{
this.hashCode = hashCode;
}
public boolean equals(Object obj)
{
return obj != null && obj.getClass().equals(getClass()) && ((MyClass)obj).otherField.equals(otherField);
}
public int hashCode()
{
return hashCode;
}
}
}
After the pointer from @jitter and a look at the source you can see why this would happen.
在来自@jitter 的指针并查看源代码之后,您会明白为什么会发生这种情况。
Like @jitter says, the java.util.HashSet
uses a java.util.HashMap
internally. When the hash changes between the first and second adda different bucket is used in the java.util.HashMap
and the object is in the set twice.
就像@jitter 说的,在内部java.util.HashSet
使用 a java.util.HashMap
。当哈希第一之间变化,并且第二添加不同的桶在使用java.util.HashMap
和对象是在该组的两倍。
The code sample may look a little contrieved but I've seen this happen in the wild with domain classes where the hash is created from mutable fields and the equals method hasn't been kept in sync with those fields.
代码示例可能看起来有点做作,但我已经看到这种情况发生在域类中,其中散列是从可变字段创建的,并且 equals 方法没有与这些字段保持同步。
回答by Thorbj?rn Ravn Andersen
An easy way to find this out is to look in the source for the code you are interested in.
找到这一点的一种简单方法是查看您感兴趣的代码的源代码。
Each JDK has a src.zip included which contains the source code for the public classes so you can just locate the source for HashSet and have a look :) I often use Eclipse for this. Start it, create a new Java project, set the JVM to be an installed JDK (if not you are using the system default JRE which doesn't have src.zip), and Ctrl-Shift-T to go to HashSet.
每个 JDK 都包含一个 src.zip,其中包含公共类的源代码,因此您只需找到 HashSet 的源代码并查看 :) 我经常为此使用 Eclipse。启动它,创建一个新的 Java 项目,将 JVM 设置为已安装的 JDK(如果不是,您使用的是没有 src.zip 的系统默认 JRE),然后按 Ctrl-Shift-T 转到 HashSet。