回答
看了你的问题更具体:
您不能Set.add添加重复,从Java文档()或你的意思是?:的addAll
添加指定的元素如果此集合尚未出现(可选操作)。更正式地说,如果该集合不包含元素e2(e == null?e2 == null:e.equals(e2)),则将指定的元素e添加到该集合中。如果此集合已包含该元素,则该呼叫将保持集合不变并返回false。结合对构造函数的限制,这可以确保集合永远不会包含重复的元素。
实际上,来自java中的源代码最多的Set
实现的AFAIK甚至不检查元素是否已被包含。
他们总是在其内部结构上执行add()
,该内部结构持有set元素并让该对象处理重复情况。
例如HashSet
在内部HashMap
上调用put(K,V)
,它只是插入新对象覆盖旧条目(如果重复)。
读一点你的问题我猜你看到奇怪的行为与java.util.HashSet
(通常是每个人默认使用)。
Contary到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;
}
}
}
从@jitter指针,看看源后,你可以看到为什么这会发生。
像@jitter说的,java.util.HashSet
在内部使用java.util.HashMap
。当散列在第一个和第二个之间变化时加入在java.util.HashMap
中使用不同的桶并且该对象在该集中两次。
代码示例可能看起来有点受损,但我已经看到这种情况发生在域类中,其中哈希是从可变字段创建的,并且equals方法未与这些字段保持同步。
一个简单的方法来找出这是从源头为您感兴趣的代码查找。
每个JDK已经包含了src.zip其中包含了公共类的源代码,这样你可以只找到HashSet的源代码并看看:)我经常使用Eclipse进行此操作。启动它,创建一个新的Java项目,将JVM设置为已安装的JDK(如果不是,则使用系统默认的JRE,它不包含src.zip),并将Ctrl-Shift-T设置为HashSet。
- 1. java.util.Set中增加了重复的条目
- 2. R中重复元素的元素
- 3. 重复元素
- 4. 重复的元素
- 5. 重复元素子元素的ID
- 6. 重复gridview元素.....!
- 7. insertAfter重复元素
- 8. WPF重复元素
- 9. 如何删除java.util.Set中的最后一个元素?
- 10. 删除重复的元素
- 11. 重复元素的Richfaces
- 12. 删除重复的元素
- 13. SimpleXML的重复元素
- 14. Android的listview重复元素
- 15. 如何在Angular中重复ng元素中的元素
- 16. 查找向量中的重复元素
- 17. 重复使用DTD中的元素
- 18. xml元素中的重复检查
- 19. 数组算法中的重复元素
- 20. 显示数组中的重复元素
- 21. 查找数组中的重复元素
- 22. 查找数组中的重复元素?
- 23. ArrayList中的重复元素(java)
- 24. 删除列表中的重复元素
- 25. C#:检查XML中的重复元素
- 26. Matlab:向量中重复的元素块
- 27. 从阵列元素中移除重复的元素
- 28. 在Excel中重复按元素的文本元素块
- 29. 解析在非重复父节点中重复的子元素
- 30. jquery重复元素创建
以修改hashCode()/ equals()结果的方式修改HashSet中的对象会产生未定义的行为。 – 2009-10-29 09:34:12
@Joachim - 确切地说,但并不意味着它不会发生。事实上,流行的IDE生成的equals/hashCode方法通常会导致hashCode随着对象的变化而改变。 – 2009-10-29 09:45:23
如果对象发生了变异,hashcode *应该改变 - 毕竟它需要与equals()一致,所以如果一个对象不再被认为等于它的预突变状态,它就需要改变。这里真正的问题是使用可变对象作为HashMap键; * *建议只使用不可变的对象,否则你打开自己的这种随机性,因为一般来说''hashCode()'*必须*随着可变对象的变化而改变。 – 2009-10-29 10:36:26