Java HashSet包含重复的条目
当equals方法表示值相同时,HashSet只存储值1。我就是这么想的 但是现在我正在向HashSet添加元素,其中equals方法返回true,并且集合的大小仍在增长??对不起,我弄糊涂了。一些我错的地方的提示会很好Java HashSet包含重复的条目,java,set,unique,hashset,Java,Set,Unique,Hashset,当equals方法表示值相同时,HashSet只存储值1。我就是这么想的 但是现在我正在向HashSet添加元素,其中equals方法返回true,并且集合的大小仍在增长??对不起,我弄糊涂了。一些我错的地方的提示会很好 Element t1 = new Element(false, false, false, false); Element t2 = new Element(true, true, true, true); Element t3 = new Element(false, fal
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());
Element t1=新元素(false,false,false,false);
元素t2=新元素(真,真,真,真);
元素t3=新元素(假,假,假,假);
如果(t1等于(t3))
System.out.println(“它们是相等的”);
Set=newhashset();
增加(t1);
增加(t2);
增加(t3);
System.out.println(“设置大小:+set.size());
因此,在本例中,我的控制台输出为:
他们是平等的套装尺寸:3件
那对我来说毫无意义。。大小是否应该为2?问题在于
元素类没有覆盖equals
和hashCode
方法,或者这些实现被破坏
从方法javadoc:
equals方法在非null对象引用上实现等价关系:
- 它是自反的:对于任何非空参考值x,x.equals(x)应该返回true
- 它是对称的:对于任何非空的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)才应返回true
- 它是可传递的:对于任何非空引用值x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)应该返回true。
它是一致的:对于任何非空引用值x和y,-x.equals(y)的多次调用始终返回true或false,前提是没有修改对象上equals比较中使用的信息
- 对于任何非空引用值x,x.equals(null)应返回false
从方法javadoc:
hashCode的总合同为:
- 在Java应用程序的执行过程中,每当在同一对象上多次调用hashCode方法时,只要没有修改对象上的equals比较中使用的信息,hashCode方法必须始终返回相同的整数。从应用程序的一次执行到同一应用程序的另一次执行,该整数不必保持一致
- 如果根据equals(Object)方法两个对象相等,那么对两个对象中的每一个调用hashCode方法必须产生相同的整数结果
- 根据equals(java.lang.Object)方法,如果两个对象不相等,则对这两个对象中的每一个调用hashCode方法都必须产生不同的整数结果,这不是必需的。但是,程序员应该知道,为不相等的对象生成不同的整数结果可能会提高哈希表的性能李>
确保这些方法的实现满足这些规则,并且您的集(由HashSet
支持)将按预期工作。您的对象具有不同的散列,因此HashSet“放置”在不同的“bucket”中。是的,我们可以使用非FINAL类的对象来实现它
在添加任何对象之前,HashSet检查两个方法hashCode()
和equals()
。
首先,它检查方法hashCode()
,如果它返回的hashCode与集合中的任何对象相同,则检查该对象的equals方法,它在内部比较两个对象的引用,即this.obj1==obj
。如果在这种情况下这些引用相同,则返回true表示该值重复。
我们可以通过重写HashCode和equals方法来添加重复的非final对象。
在HashCode()中,如果参数相同,则可以返回相同的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
注意:在不重写这些方法的情况下,输出将是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();
}
}
希望这能有所帮助。有点输入错误。我没有选择t2.equals(t3),而是选择了t1.equals(t3),它说t1和t3根据它们的equals方法是相等的阅读我的答案,你还需要重写hashCode
方法。我的元素有一个equals方法,它检查4个布尔值,如果它们相同,它返回true。我得到的输出(“它们是相等的”)表明,相等的方法应该有效/equals确实已经实现。@tobiSet
使用equals
和hashCode
方法。您的元素
类也必须重写hashCode
方法,以使集合
按预期工作。如果这没有反映在我的答案中,请刷新页面。好的,这可能就是答案。。我试试看,谢谢。但是我对hashCode方法的需要有点困惑,因为sets add方法的doc说:更正式地说,如果这个集合不包含元素e2,那么将指定的元素e添加到这个集合中(e==null?e2==null:e.equals(e2))。(与hashCode无关)@tobi除非您重写hashCode()
以及equals()
,否则您违反了这些方法的约定。仅仅因为HashSet#add()
的Javadoc没有引用hashCode()
并不意味着可以忽略equals()
和hashCode()
contracts。当然给出了解决方案。我只是告诉了逻辑,在添加到集合中之前如何比较元素。因此,必须重写这两种方法才能创建重复条目。如果它们的hashcode()返回的值不同,那么就没有必要重写equals()。我注意到duplicate对象的hashcode与您所说的相同。但如何解决多回路的问题呢?