如何在与Equal和hashcode

时间:2017-06-28 21:33:18

标签: java equals hashset hashcode

我有一个产品类,其中有三个变量:

class Product implements Comparable<Product>{
   private Type type;                 // Type is an enum
   Set<Attribute> attributes;        // Attribute is a regular class
   ProductName name;                 // ProductName is another enum
} 

我使用Eclipse自动生成equal()和hashcode()方法:

@Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((attributes == null) ? 0 : attributes.hashCode());
        result = prime * result + ((type == null) ? 0 : type.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Product other = (Product) obj;
        if (attributes == null) {
            if (other.attributes != null)
                return false;
        } else if (!attributes.equals(other.attributes))
            return false;
        if (type != other.type)
            return false;
        return true;
    }

现在在我的应用程序中,我需要对一组产品进行排序,因此我需要实现Comparable接口和compareTo方法:

@Override
    public int compareTo(Product other){
        int diff = type.hashCode() - other.getType().hashCode();
    if (diff > 0) {
        return 1;
    } else if (diff < 0) {
        return -1;
    }

    diff = attributes.hashCode() - other.getAttributes().hashCode();

    if (diff > 0) {
        return 1;
    } else if (diff < 0) {
        return -1;
    }

    return 0;
    }

这种实施有意义吗?如果我只想根据“类型”和“属性”值的字符串值对产品进行排序,那该怎么办?那么如何实现呢?

编辑: 我想要对一组Set进行排序的原因是因为我有Junit测试,它在HashSet的字符串值上断言。我的目标是在对集合进行排序时保持相同的输出顺序。否则,即使Set的值相同,由于集合的随机输出,断言也会失败。

EDIT2: 通过讨论,很明显,在单元测试中断言HashSet的String值的相等性并不好。对于我的情况,我目前编写一个sort()函数来按自然顺序对HashSet字符串值进行排序,因此它可以为我的单元测试一致地输出相同的String值,现在就足够了。谢谢大家。

2 个答案:

答案 0 :(得分:1)

从这里的所有评论看起来你根本不需要使用Comparator。这是因为:

1)您使用的HashSetComparator不兼容。它没有订购。

2)您只需要确保包含HashSet的两个Product相等。这意味着它们大小相同并包含相同的Product s。

由于您已将hashCodeequals方法添加到Product,所有您需要做的就是在equals上调用HashSet方法。

HashSet<Product> set1 = ...
HashSet<Product> set2 = ...

assertTrue( set1.equals(set2) );

答案 1 :(得分:0)

这种实现似乎并不一致。您无法控制hash codes的外观。如果您在第一次尝试时根据obj1 < obj2获得了compareTo,则下次启动JVM时,obj1 > obj2可能会相反。{/ p>

你真正知道的唯一事情是,如果diff == 0那么对象被认为是相等的。但是,您也可以使用equals方法进行该检查。

现在由您决定何时定义obj1 < obj2obj1 > obj2。只要确保它是一致的。

顺便提一下,您知道当前的实施在ProductName name检查中不包含equals吗?不知道这是不是意图。

问题是,您对这些属性了解多少?也许他们实施Comparable(例如,如果他们是Number s),那么您可以根据他们的compareTo方法进行排序。如果你对这些对象完全一无所知,那么就很难建立一致的顺序。

如果你只是希望它们被一致地排序,但是排序本身不起作用,你可以在创建时给它们id并按它们排序。此时你确实可以使用哈希码,如果它可以在JVM次调用之间发生变化并不重要,但仅限于此。