我有一个如下课程(Bean):
class KeysHolder {
Long kitId;
String packId;
String boxId;
// getters and setters
.......
// @Override equals and hashCode
}
我有一个包含上述对象的集合
Set<KeysHolder> keys;
现在,如果我继续将对象添加到集合中,它是否会根据每个元素的值自动删除重复项? (我知道它在内部使用了重写的equals和hashCode方法。)
最终集不应包含基于每个字段相等的任何重复项。
obja.kitId = objb.kitId
objb.packid = objb.packId
obja.boxId = objb.boxId
谢谢!
答案 0 :(得分:6)
现在,如果我继续将对象添加到集合中,它是否会根据每个元素的值自动删除重复项。
如果Set
实现发现重复的元素,则根本不会插入。
来自HashSet#add(E e)的Javadoc:
如果指定的元素尚不存在,则将其添加到此集合中。更正式地说,如果此集合不包含元素e2,使得(e == null?e2 == null:e.equals(e2)),则将指定的元素e添加到此集合中。如果此set已包含该元素,则调用将保持set不变并返回false。
答案 1 :(得分:2)
是的,任何Set
实施都不允许重复。
但是,它有一个警告。对于Set
和其他基于哈希的集合,您需要确保您尝试插入的对象正确覆盖其equals()
和hashCode()
方法。
正确的说,我的意思是equals()
应该为两个有意义的等效对象返回true
,并且hashCode()
应该尝试为您的对象范围尽可能不同的值返回输入集。
虽然不恰当的equals()
实施很可能会破坏您的计划;效率低下的hashCode()
实施会降低Set
的效果,例如add()
,contains()
等操作会像执行一样慢。
答案 2 :(得分:2)
简短回答是是,任何一组都会自行执行重复数据删除。但只有在尊重合同的情况下才能保证;并且每个Set
实现的合同有点不同:
对于HashSet
,正如您所注意到的,您必须实施hashCode()
和equals()
。但这还不够:如果您在HashSet
中保留可变实例并修改影响hashCode()
/ equals()
结果的属性,您仍将结束在奇怪的情况下。
另一方面,使用TreeSet
,您需要确保Comparable.compareTo()
或Comparator.compare()
方法与equals()
一致。
请阅读Set
的文档以及适合您需求的实际实现文档,并尝试遵守合同。
答案 3 :(得分:1)
HashSet在内部使用HashMap,这个地图用key维护,因为你要在set中添加的值和value是Object类的一个实例( final private static final Object PRESENT = new Object(); 强>)。现在,当您向此集添加相同的对象时,它与map在同一个键上使用相同的map.put进行相同的操作,只需更新该值。
但是,要更新的值仍然与 PRESENT 相同。因此,在某种程度上,您可以说该集合不会添加相同的值。虽然实际上,内部用于实现此集的地图正在使用 * 相同的 键 *和相同的值(PRESENT)进行更新。
答案 4 :(得分:0)
我已经写了一个示例来说明如何在班级的一个字段(此处为name
)中删除重复的员工条目:
public class Employee {
private String id;
private String name;
private String age;
public Employee(String i, String n, String a) {
id = i; name = n; age = a;
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Employee)) {
return false;
}
Employee e = (Employee) obj;
return name.equals(e.name);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public String toString() {
return id + " " + name + " " + age;
}
public static void main(String[] args) {
Employee e1 = new Employee("1", "abc", "10");
Employee e2 = new Employee("2", "def", "20");
Employee e3 = new Employee("3", "abc", "30");
HashSet<Employee> empSet = new HashSet<>();
empSet.add(e1);
empSet.add(e2);
empSet.add(e3);
System.out.println(empSet.toString());
}
}
我要做的就是在Employee类中重写方法hashCode
和equals
。它打印:
[1 abc 10, 2 def 20]