java.util.Set中的重复元素

Neo*_*Neo 11 java set

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

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

jit*_*ter 14

实际上来自SetJava中大多数实现的来源的AFAIK 甚至不检查该元素是否已被包含.

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

例如,对内部的HashSet调用只是插入新对象,如果重复则覆盖旧条目.put(K,V)HashMap


Nic*_*olt 11

仔细阅读你的问题我猜你正在看到一个奇怪的行为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<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;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

就像@jitter说的那样,内部java.util.HashSet使用了一个java.util.HashMap.当第一和第二之间的散列变化添加不同的桶在使用java.util.HashMap和对象是在该组的两倍.

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

  • 可以说,如果对象被突变,哈希码*应该*改变 - 毕竟,它需要与`equals()`一致,所以如果一个对象不再被认为等于它的突变前状态,它需要改变.这里真正的问题是使用可变对象作为HashMap键; 高度*建议只使用不可变对象,否则你会打开这种随机性,一般来说`hashCode()`*必须*随着可变对象的变化而改变. (4认同)
  • 以修改其hashCode()/ equals()结果的方式修改HashSet中的对象会产生未定义的行为. (2认同)

Tom*_*mas 0

更详细地阅读您的问题:

您无法添加重复项,来自 Set.add() 的 java doc 还是您的意思是 addAll?:

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