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