[英]Need clarification about HashSet and duplicates in Java
我需要澄清一下java认为重复的内容。
请考虑以下代码:
public class Fruit {
private String name;
private int juice;
public Fruit(String name, int j) {
this.name=name;
this.juice=j;
}
//some more code here
public String toString() {
return this.name;
}
public boolean equals(Object fruit) {
return (((Fruit)fruit).name.equals(this.name));
}
}
public class Test {
public static void main(String[] args) {
Fruit a=new Fruit("Apple", 25);
Fruit b=new Fruit("Apple", 22);
HashSet<Fruit> hs=new HashSet<Fruit>();
hs.add(a);
hs.add(b);
System.out.println(a.equals(b));
System.out.println(hs.size());
}
}
我创建了一个Fruit类,我重写了equals(),因此如果两个对象的名称相等,则认为它们是等于的。 然后,我将两个Fruit对象(具有相同的名称)添加到HashSet中。
现在,HashSet应该阻止尝试添加两个相等的对象。 虽然,上面代码的输出是:
真2
所以一方面,Java认为这两个对象(a和b)是等于的,另一方面,HashSet并不认为这两个对象是等价的。 那我在这里错过了什么?
提前致谢!
HashSet不认为这两个是平等的。 那我在这里错过了什么?
您错过了在Fruit
类中覆盖hashCode
。
@Override
public int hashCode(){
return 31 * this.name.hashCode();
}
如果它是equals()
则是重复,否则不是。 如果你想确保它做你想要的覆盖equals()
方法。
您还必须覆盖hashCode
方法,因为HashSet
在内部使用HashMap
。 如果您使用像Eclipse这样的工具,您可以使用它轻松生成两者。
这是hashCode()
方法中的问题。 你必须覆盖equals()
和hashCode()
方法。
首先,你实现equals
是错误的。 您将参数转换为Fruit
而不先检查它是否实际上是Fruit
的实例。
其次,当覆盖equals
你也必须覆盖hashCode
。 请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()
HashSet和HashMap使用两件事来检查是否相等。
首先,它使用getHashCode()检查HashCode中的两个对象。
当且仅当HashCode匹配它时,使用equals()方法检查相等性。
如果equals返回true,则认为对象是相同的。
每当在方法中实现equals时,您还必须实现HashCode,并且需要遵循两种方法的行为。 如果你没有像HashMap,HashSet等那样的东西都有未定义和不正确的行为。
您可以在此处查看详细说明: http : //www.programcreek.com/2011/07/java-equals-and-hashcode-contract/
Netbeans(以及大多数其他IDE)能够为您自动生成equals和hash代码方法。 只需转到source-> insert code-> equals和hash code
然后,您可以选择要包含的字段,它将为您正确生成两种方法。
Hashset和HashMap在内部调用两个方法来检查相等性。
首先它检查HashCode,因为if对象已经在桶中,它将使用equals方法检查相等性。
在您的情况下,您已重写equals方法但忘记覆盖Hashcode。
@Override
public int hashCode(){
return "Hash"+ this.name.hashCode();
}
这将为您提供正确的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.