有什么方法可以覆盖Set
数据类型使用的equals
方法吗?我为一个名为Fee
的类编写了一个自定义的equals
方法。现在我有一个Fee
的LnkedList
,我想确保没有重复的条目。因此,我正在考虑使用Set
而不是LinkedList
,但决定两个费用是否相等的标准存在于Fee
类中的overriden equals
方法中。
如果使用LinkedList
,我将不得不遍历每个列表项,并调用Fee
类中的overriden equals
方法,将其余项作为参数。单独阅读这篇文章听起来处理太多,会增加计算复杂性。
我可以将Set
与重写的equals
方法一起使用吗?我应该吗?
正如Jeff Foster所说:
Set.equals()方法仅用于比较两个集合的相等性。
您可以使用Set
来消除重复的条目,但要注意:HashSet
不使用其包含对象的equals()
方法来确定相等性。
HashSet
携带带有<Integer(HashCode), Object>
条目的内部HashMap
,并使用equals()以及HashCode的equals方法来确定相等性。
解决该问题的一种方法是覆盖您放入集合中的类中的hashCode()
,使其代表您的equals()
标准
例如:
class Fee {
String name;
public boolean equals(Object o) {
return (o instanceof Fee) && ((Fee)o.getName()).equals(this.getName());
}
public int hashCode() {
return name.hashCode();
}
}
您可以也应该使用Set来保存具有重写的equals方法的对象类型,但您可能也需要重写hashCode()相等的对象必须具有相等的哈希代码。
例如:
public Fee{
public String fi;
public String fo;
public int hashCode(){
return fi.hashCode() ^ fo.hashCode();
}
public boolean equals(Object obj){
return fi.equals(obj.fi) && fo.equals(obj.fo);
}
}
(当然,必要时进行空检查。)
集合经常使用hashCode()来优化性能,如果您的hashCode方法被破坏,则会出现错误行为。例如,HashSet使用内部HashMap。
如果你检查HashMap的源代码,你会发现它依赖于元素的hashCode()和equals()方法来确定相等性:
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
如果未正确生成哈希,则可能永远不会调用equals方法
为了加快设置速度,应尽可能为不相等的对象生成不同的哈希代码。
Set
使用添加到集合中的对象的equals方法。JavaDoc声明
不包含重复元素的集合。更正式地说,集合不包含一对元素e1和e2,因此e1.equals(e2),最多包含一个null元素。
Set.equals()
方法仅用于比较两个集合是否相等。它从未被用作从集合中添加/删除项目的一部分。
一种解决方案是使用带有比较器的TreeSet。
来自文件:
TreeSet实例使用其compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,该方法认为相等的两个元素是相等的。
这种方法比使用LinkedList快得多,但比HashSet慢一点(ln(n)vs n)。
值得注意的是,使用TreeSet的一个副作用是对集合进行排序。
Apache Commons Collection 中存在PredicatedList或PredicatedSet