我有一个产品类,其中有三个变量:
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值,现在就足够了。谢谢大家。
答案 0 :(得分:1)
从这里的所有评论看起来你根本不需要使用Comparator
。这是因为:
1)您使用的HashSet
与Comparator
不兼容。它没有订购。
2)您只需要确保包含HashSet
的两个Product
相等。这意味着它们大小相同并包含相同的Product
s。
由于您已将hashCode
和equals
方法添加到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 < obj2
或obj1 > obj2
。只要确保它是一致的。
顺便提一下,您知道当前的实施在ProductName name
检查中不包含equals
吗?不知道这是不是意图。
问题是,您对这些属性了解多少?也许他们实施Comparable
(例如,如果他们是Number
s),那么您可以根据他们的compareTo
方法进行排序。如果你对这些对象完全一无所知,那么就很难建立一致的顺序。
如果你只是希望它们被一致地排序,但是排序本身不起作用,你可以在创建时给它们id
并按它们排序。此时你确实可以使用哈希码,如果它可以在JVM
次调用之间发生变化并不重要,但仅限于此。