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);
        }
    }