你好,我可能会监督一些事情,但现在就去了
我有一个TreeSet<CustomObject>
,我不想在Set中有重复项。我的CustomObject
课程看起来像这样。
class CustomObject implements Comparable<CustomObject> {
String product;
String ean;
public CustomObject(String ean){
this.ean = ean;
// product is getting set via setter and can be null
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CustomObject that = (CustomObject) o;
return ean.equals(that.ean);
}
@Override
public int hashCode() {
return ean.hashCode();
}
@Override
public int compareTo(CustomObject another) {
if(equals(another)) return 0;
if(product != null && another.product == null) return -1;
if(product == null) return 1;
return product.compareToIgnoreCase(another.product);
}
}
现在我为新对象添加了一个函数。
private final TreeSet<CustomObject> productCatalog;
public void addObject(SomeData tag) {
CustomObject p = new CustomObject(tag.getEan());
if (productCatalog.contains(p)) { // <-- This checks only one entry of the Set.
for (CustomObject temp : productCatalog) {
if (temp.equals(p)) {
p = temp; // I do stuff with that later which is irrelevent here
}
}
} else {
productCatalog.add(p);
}
}
方法productCatalog.contains(p)
从compareTo
接口调用Comparable
方法并进行比较。这里的问题是,它只是检查我认为最后一个对象?在集合中。所以会发生的是只存在一个唯一的CustomObject条目。
这是我使用调试器跟随它的情况:
productCatalog.contains(p)
compareTo
equals
以检查ean.equals(that.ean)
如何让它不仅检查步骤4中的一个对象,还检查Set中的所有当前对象。我错过了什么?
THX!
编辑:这些是一些示例数据。为简单起见SomeData tag
基本上是一个字符串。
First run:
addObject("Ean1") // success added
addObject("Ean2") // success added
addObject("Ean3") // success added
addObject("Ean4") // success added
所有内容都会添加到TreeSet中。
Second run:
addObject("Ean1") // failed already in the map
addObject("Ean2") // failed already in the map
addObject("Ean3") // failed already in the map
addObject("Ean5") // success added
addObject("Ean4") // success added
addObject("Ean4") // success added
出于测试目的,我根据字符串ean
手动设置产品名称。
public CustomObject(String ean){
this.ean = ean;
switch(ean){
case "Ean1": product = "TestProduct"; break;
case "Ean2": product = "ProductTest";break;
case "Ean3": product = "Product";break;
}
TreeSet
充当缓存。
Edit2:这就是我解决它的方法。
for (CustomObject temp : productCatalog) {
if (temp.equals(p)) {
p = temp; // I do stuff with that later which is irrelevent here
}
}
我使用contains
方法删除了if语句,因为它始终返回'1 or
- 1 in my special case. Now I simply iterate over the Set to correctly use the
equals`方法,因为TreeSet使用compareTo()来检查每个元素集。
Java Docs陈述以下内容
注意由一组维护的排序(无论是否显式 比较器提供)必须与equals一致,如果是的话 正确实现Set接口。 (参见可比较者或比较者 对于与equals一致的精确定义。)就是这样 因为Set接口是根据equals操作定义的, 但 TreeSet实例使用它执行所有元素比较 compareTo(或compare)方法,因此两个被认为相等的元素 从该集合的角度来看,通过这种方法是相等的。该 集合的行为即使其排序不一致也是明确定义的 与...平等它只是没有遵守集合的一般合同 接口
答案 0 :(得分:1)
主要问题:
如果product和other.product都为null,则 compareTo
会返回1。这是错误的,因为它们实际上是平等的。您可能忘记为更高的ean值设置产品名称,例如&#34; Ean4&#34;和&#34; Ean5&#34;。
旧答案:
equals
和compareTo
的实施不适合。
equals
适用于产品上的ean和compareTo
。这只有在您隐含地假设等于ean意味着同等产品时才有效。如果在您的测试用例中不是这样,那么结果将是错误的。
在任何一种情况下,都不是很好的实施,因为这可能导致&lt; b,b&lt; c但是等于&#34;等于&#34;角