Java Set集合 – 覆盖equals方法
有没有办法覆盖Set
数据类型使用的equals
方法? 我为一个名为Fee
的类编写了一个自定义equals
方法。 现在我有一个LnkedList
Fee
LnkedList
,我想确保没有重复的条目。 因此,我正在考虑使用LinkedList
一个Set
insted,但是决定两个费用是否相等的标准存在于Fee
类中的overriden equals
方法中。
如果使用LinkedList
,我将不得不遍历每个列表项并在Fee
类中调用overriden equals
方法,其余条目作为参数。 仅仅阅读这个听起来像是太多的处理并且会增加计算复杂性。
我可以使用带有重写的equals
方法的Set
吗? 我是不是该?
正如杰夫福斯特所说:
Set.equals()方法仅用于比较两组的相等性。
您可以使用Set
来删除重复的条目,但要注意: HashSet
不使用其包含对象的equals()
方法来确定相等性。
HashSet
携带带有
条目的内部HashMap
,并使用equals()以及HashCode的equals方法来确定相等性。
解决此问题的一种方法是覆盖放在Set中的Class中的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方法被破坏,则会出现exception。 例如, 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