Java Set集合 - 覆盖equals方法

时间:2011-05-31 12:02:46

标签: java set override equals

有没有办法覆盖equals数据类型使用的Set方法?我为一个名为equals的类编写了一个自定义Fee方法。现在我有一个LnkedList Fee,我想确保没有重复的条目。因此,我正在考虑使用Set LinkedList equals,但决定两项费用是否相等的标准存在于Fee类的重写LinkedList方法中。< / p>

如果使用equals,我将不得不遍历每个列表项并在Fee类中调用覆盖Set方法,其余条目作为参数。仅仅阅读这个听起来就像是处理太多而且会增加计算复杂性。

我可以将equals与重写{{1}}方法一起使用吗?我应该吗?

5 个答案:

答案 0 :(得分:33)

正如杰夫福斯特所说:

  

Set.equals()方法仅用于比较两组的相等性。

您可以使用Set删除重复的条目,但要注意:HashSet不使用其包含对象的equals()方法来确定相等。

HashSet带有HashMap<Integer(HashCode), Object>个条目,并使用equals()以及 HashCode 的equals方法来确定相等。< / p>

解决此问题的一种方法是覆盖您在Set中放入的类中的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();
  }

}

答案 1 :(得分:8)

您可以而且应该使用Set来保存具有重写的equals方法的对象类型,但您也可能需要覆盖hashCode()。 Equal对象必须具有相同的哈希码。

例如:

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 uses an internal HashMap.

If you check the source code of HashMap,您将看到它依赖于元素的hashCode()和equals()方法来确定相等性:

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

如果未正确生成哈希,则可能永远不会调用您的equals方法。

为了让你的设置更快,你应该尽可能为不相等的对象生成不同的哈希码。

答案 2 :(得分:5)

Set使用添加到集合中的对象的equals方法。 JavaDoc

  

不包含重复元素的集合。更正式地说,集合不包含元素e1和e2对,例如e1.equals(e2),最多只有一个null元素。

Set.equals()方法仅用于比较两个集合的相等性。它从未用作添加/删除集合中项目的一部分。

答案 3 :(得分:2)

一种解决方案是将TreeSet与比较器一起使用。

来自文档:

  

TreeSet实例使用compareTo(或compare)方法执行所有元素比较,因此从集合的角度来看,这个方法认为相等的两个元素是相等的。

这种方法比使用LinkedList快得多,但比HashSet慢一点(ln(n)vs n)。

值得注意的是,使用TreeSet的一个副作用是您的集合已经排序。

答案 4 :(得分:-1)

Apache Commons Collection

中有PredicatedList或PredicatedSet