TreeSet Comparator执行不一致

时间:2014-10-10 19:19:53

标签: java

请参阅以下两个类DTODTOWithOrdering

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

DTOWIthOrderingDTO延伸,并覆盖equalscompareTo方法。

当我创建TreeSet<DTOWIthOrdering>并在此调用包含

时,以下代码片段出现问题
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);
        }
    }

当我在我的程序中运行时,我可以看到treeSet包含2700多个实体,其中一个实体的密钥为0b3ae620-bbcf-347d-a9b4-87e6fd765cd7,recordVersionNumber为4

但是,其中一个diff实体包含相同的键,其recordVersionNumber为0。

当代码调用contains方法时,set返回值false。

奇怪的是,对于其他示例,其中键相等且TreeSet中的记录版本号更大,它返回true!

我的逻辑在这里有什么问题吗?

1 个答案:

答案 0 :(得分:3)

以下是JavaDoc对Comparable接口的引用:

  

int compareTo(T o)

     

将此对象与指定的订单对象进行比较。返回一个   负整数,零或正整数,因为此对象较少   比,等于或大于指定的对象。实施者   必须确保所有x和s的sgn(x.compareTo(y))== -sgn(y.compareTo(x))   年。 (这意味着x.compareTo(y)必须抛出异常   y.compareTo(x)抛出异常。)

如果您返回-1但永远不会返回1,则属性为    sgn(x.compareTo(y)) == -sgn(y.compareTo(x))不能成立。因此,您对此方法的实现不符合规范,TreeSet可能无法正常工作。