Java 树集比较器执行不一致
请参见以下两个类,Java 树集比较器执行不一致,java,Java,请参见以下两个类,DTO和DTOWithOrdering: public class DTO { private final String key; private final long recordVersionNumber; public DTO(String key) { this.key = key; this.recordVersionNumber = 0; } public DTO(String key,
DTO
和DTOWithOrdering
:
public class DTO {
private final String key;
private final long recordVersionNumber;
public DTO(String key) {
this.key = key;
this.recordVersionNumber = 0;
}
public DTO(String key, long recordVersionNumber) {
this.key = key;
this.recordVersionNumber = recordVersionNumber;
}
public String getKey() {
return key;
}
public long getRecordVersionNumber() {
return recordVersionNumber;
}
@Override
public String toString() {
return "Key: " + this.key + " Record Version Number: " + this.recordVersionNumber;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DTO that = (DTO) o;
return Objects.equal(this.key, that.key) &&
Objects.equal(this.recordVersionNumber, that.recordVersionNumber);
}
@Override
public int hashCode() {
return Objects.hashCode(key, recordVersionNumber);
}
public class DTOWithOrdering extends DTO implements Comparable<DTOWithOrdering> {
public DTOWithOrdering(String key, long recordVersionNumber) {
super(key, recordVersionNumber);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DTOWithOrdering other = (DTOWithOrdering) o;
if(this.getKey().equals(other.getKey())) {
if(this.getRecordVersionNumber() == other.getRecordVersionNumber()) {
return true;
} else if(this.getRecordVersionNumber() <= other.getRecordVersionNumber()) {
return true;
} else {
return false;
}
} {
return false;
}
}
@Override
public int compareTo(DTOWithOrdering other) {
if(this.getKey().equals(other.getKey())) {
if(this.getRecordVersionNumber() == other.getRecordVersionNumber()) {
return 0;
} else if(this.getRecordVersionNumber() <= other.getRecordVersionNumber()) {
return 0;
} else {
return -1;
}
} {
return -1;
}
}
}
当我在程序中运行此命令时,我可以看到treeSet包含2700多个实体,其中一个实体的键为0b3ae620-bbcf-347d-a9b4-87e6fd765cd7,记录版本号为4
但是,其中一个diff实体包含recordVersionNumber为0的同一个键
当代码调用contains方法时,集合返回一个值false
奇怪的是,对于其他示例,在树集中键相等且记录版本号更大的情况下,它返回true
我的逻辑有问题吗?以下是JavaDoc对
Compariable
接口的引用:
国际比较组织(TO)
将此对象与订单的指定对象进行比较。返回一个
负整数、零或正整数,因为此对象小于
大于、等于或大于指定对象。实施者
必须确保所有x和x的sgn(x.compareTo(y))==-sgn(y.compareTo(x))
Y(这意味着x.compareTo(y)必须在以下情况下引发异常:
y、 compareTo(x)引发异常。)
如果返回-1
,但从未返回1
,则属性sgn(x.compareTo(y))==-sgn(y.compareTo(x))
不能为真。因此,此方法的实现不符合规范,TreeSet
可能无法正常工作 DTOWithOrdering
方法中的compareTo
看起来很奇怪,因为它从不返回1
。您确定它完全符合您的要求吗?作为旁注,这是一个很好的例子,在compareTo
上进行单元测试可能会识别和诊断错误。它必须返回1吗?我承认它是一个低效的比较器,因为它实际上是一个列表,但这能解释为什么contains()返回false吗?我认为,逻辑是相反的,在你的equals()
,另一个来自diff
(包含使用equals
)。当比较器返回0
时,这意味着两个对象相等,这将被排序的集合(如TreeSet
)所遵循。然后说if(this.getRecordVersionNumber()
TreeSet<DTOWithOrdering> treeSet = new TreeSet<DTOWithOrdering>(keyAndVersionList);
List<DTO> results = new ArrayList<DTO>();
for (DTO diff : diffs) {
if (treeSet.contains(new DTOWithOrdering(diff.getKey(), diff.getRecordVersionNumber())) == false) {
results.add(diff);
}
}