java.util.Set中的重复元素

java.util.Set实现删除重复的元素。

如何在java.util.Set内部删除重复元素?

实际上来自Java中的大多数Set实现的AFAIK甚至不检查元素是否已被包含。

它们总是在其内部结构上执行add() ,它保存set元素并让该对象处理重复的情况。

例如, HashSet调用put(K,V)放在内部HashMap ,如果重复, HashMap插入新对象覆盖旧条目。

仔细阅读你的问题我猜你正在看到java.util.HashSet奇怪行为(通常是每个人默认使用的)。

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 set = new HashSet(); 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; } } } 

在来自@jitter的指针并查看源代码后,您可以看到为什么会发生这种情况。

就像@jitter所说的那样, java.util.HashSet在内部使用了java.util.HashMap 。 当散列在第一个和第二个之间发生变化时,在java.util.HashMap使用不同的桶,并且该对象在集合中两次。

代码示例可能看起来有点受欢迎,但我已经看到这种情况发生在域类中,其中哈希是从可变字段创建的,并且equals方法尚未与这些字段保持同步。

找到这个的简单方法是查看您感兴趣的代码的源代码。

每个JDK都包含一个src.zip,其中包含公共类的源代码,因此您只需找到HashSet的源代码并查看:)我经常使用Eclipse。 启动它,创建一个新的Java项目,将JVM设置为已安装的JDK(如果不是,您使用的是没有src.zip的系统默认JRE),并使用Ctrl-Shift-T转到HashSet。

更详细地阅读您的问题:

你不能在java doc for Set.add()中添加重复项,或者你的意思是addAll?:

如果指定的元素尚不存在,则将其添加到此集合(可选操作)。 更正式地,如果集合不包含元素e2,则将指定的元素e添加到该集合中(e == null?e2 == null:e.equals(e2))。 如果此set已包含该元素,则调用将保持set不变并返回false。 结合对构造函数的限制,这可以确保集合永远不会包含重复元素。