HashSet中包含重复的条目(HashSet contains duplicate entries

2019-09-01 05:42发布

只存储一个HashSet值亲人,当equals方法说,它们是相同的。 那正是我所想。

但现在我将元素添加到HashSet的地方equals方法返回true并且集的大小还是增长? 抱歉,我很困惑。 一些提示在那里我错了就好了。

Element t1 = new Element(false, false, false, false);
Element t2 = new Element(true, true, true, true);
Element t3 = new Element(false, false, false, false);

if (t1.equals(t3))
    System.out.println("they're equal");

Set<Element> set = new HashSet<>();

set.add(t1);
set.add(t2);
set.add(t3);

System.out.println("set size: " + set.size());

所以在这个例子我的控制台输出:

他们是平等的
集大小:3

这是没有意义的我..不该大小为2?

Answer 1:

问题是,你的Element类有没有覆盖的equalshashCode方法或这些实现都断了。

Object#equals方法的javadoc:

equals方法实现对非空对象引用的一个等价关系:

  • 自反性:对于任何非空的参考值x,x.equals(x)应返回true。
  • 对称性:对于任何非空的参考值x和y,x.equals(y)的应返回true,当且仅当y.equals(x)返回真。
  • 传递性:对于任何非空引用值x,y和z,如果x.equals(Y)返回true并且y.equals(z)返回true,那么x.equals(z)应返回true。 它是一致的:对于任何非空引用值x和y,的-x.equals(y)的多个调用始终返回true或始终返回假,没有设置中使用的信息等于在对象上比较被修改。
  • 对于任何非空引用值x,x.equals(空)应该返回false。

Object#hashCode方法的javadoc:

hashCode的一般合同是:

  • 每当它是一个Java应用程序的执行期间,在同一对象上调用一次以上,hashCode方法必须一致地返回相同的整数,没有设置中使用的信息等于在对象上比较被修改。 该整数不必从一个应用的执行保持一致,以同一应用程序的另一执行。
  • 如果两个对象根据equals(Object)方法是相等的,则调用在每个两个对象的hashCode方法必须产生相同的整数结果。
  • 这不是必需的:如果两个对象根据equals(java.lang.Object)方法是不相等的,然后调用hashCode方法在各两个对象的必须产生不同的整数结果。 但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。

确保这些方法的实现满足这些规则和您的Set (由支持HashSet )会正常运行。



Answer 2:

你的对象有不同的散列所以HashSet的“放”,然后在不同的“桶”。



Answer 3:

如果你有自己的模型类,你需要改变一些基本功能的工作就像在下面的例子来完成。

执行代码:

HashSet<MyModel> models = new HashSet<MyModel>();

for (int i = 1; i < 5; i++)
    models.add(new MyModel(i + "", "Name :" + i + ""));

for (int i = 3; i < 5; i++)
    models.add(new MyModel(i + "", "Name :" + i + ""));

for (Object object : models)
    System.out.println(object);

模型类:

/**
 * Created by Arun
 */
public static class MyModel {

    private String id = "";
    private String name = "";

    public MyModel(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return getId();
    }

    @Override
    public boolean equals(Object obj) {
        return !super.equals(obj);
    }

    public int hashCode() {
        return getId().hashCode();
    }

}

希望这可以帮助。



Answer 4:

是的,我们可以用这不是最终的类的对象实现它。

HashSet的支票两种方法hashCode()equals()添加任何对象之前。 首先它检查方法hashCode() ,如果它返回的哈希码是相同的任何组中的对象,然后它检查该对象,其在内部的参考文献中两个对象即比较equals方法this.obj1==obj 。如果这些是在这种情况下,相同的附图标记,则返回true意味着它是一个重复的值。 我们可以通过重写的hashCode添加重复的非最终目标和equals方法。 在hashCode()方法,你可以在同样的参数的情况下返回相同的哈希码。

见例如:

public class Product {
int i;
Product(int a)
{
    this.i=a;
}
@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + i;
    return result;
}
@Override
public boolean equals(Object obj) {
    /*if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Product other = (Product) obj;
    if (i != other.i)
        return false;
    return true;*/
    return true;
}
}
`

`
import java.util.HashSet;
import java.util.Set;
public class Main {
public static void main(String[] args) {
    Product p1=new Product(1);
    Product p2=new Product(1);
    Product p3=new Product(1);
    Set s=new HashSet();
    s.add(p1);
    s.add(p2);
    s.add(p3);
    System.out.println(s.size());
}
}

输出将是1。

PS:如果不重写这些方法,输出将是3,因为它会使用它们的默认行为。



文章来源: HashSet contains duplicate entries