订单对象比较

时间:2014-06-03 07:50:27

标签: java object comparator comparable

这是我的目标:

public class TrackUserChanges{
    private Long id;
    private Long previous;
}

我有一个ArrayList。我想像这样排序对象: - 如果来自一个对象的getPrevious()等于来自另一个对象的getId,则将第一个对象与具有该值的对象放在getId()上。

我已经在课堂上有一个compareTo方法,我不想打破它。所以我创建了一个方法:

public int compareTrack(TrackUserChanges o){

    if(this.getPrevious().equals((o.getId()))){
        return -1;
    }
    ??return this.getPrevious().compareTo(o.getId());

}

不好。有什么想法吗?

示例:id,上一个

TrackUserChanges t = new TrackUserChanges ( 2,1)
TrackUserChanges t1 = new TrackUserChanges ( 3,1)
TrackUserChanges t2 = new TrackUserChanges ( 1,1)

在这种情况下t.getPrevious()= t2.getId()然后我想要这个顺序:t2,t,t1

3 个答案:

答案 0 :(得分:0)

你要做的不是一个好主意。

请阅读compareTo()的合同:

  

实现者必须确保sgn(compare(x,y))==   所有x和y的-sgn(比较(y,x))。 (这意味着当且仅当compare(y,x)抛出时,compare(x,y)必须抛出异常   异常。)

     

实现者还必须确保关系是可传递的:   ((compare(x,y)> 0)&&(compare(y,z)> 0))暗示比较(x,z)> 0。

     

最后,实现者必须确保compare(x,y)== 0暗示   所有z的sgn(compare(x,z))== sgn(compare(y,z))。

如果您有a(1,2)b(2,1),则他们不会反身:a.compareTo(b)b.compareTo(a)都返回相同的符号,这违反了第一条规则。

您还没有想过如何处理a(1,2)b(3,4)之间的比较。我怀疑你是否可以使它具有传递性和反思性。

告诉我们你为什么需要这样做,而且可能有更好的选择。

答案 1 :(得分:0)

你必须比较类似的东西。

    public class TrackUserChanges {
        private Long    id;
        private Long    previous;
    }

    public int compareTrack(TrackUserChanges o) {
        int diff = this.getId().compareTo(o.getId()); 
        if (diff != 0) {
            return diff;
        } else {
            return this.getPrevious().compareTo(o.getPrevious());
        }
    }

您无法将ID与之前的ID进行比较,即使它们都是Long值。

答案 2 :(得分:0)

你可以使用Comparator如下,但我认为这是不可取的,原因如下:

// XXX: Untested code
public int compare(TrackUserChanges tuc1, TrackUserChanges tuc2) {
    return tuc1.getId() - tuc2.getPreviousId(); 
}

或...按先前的ID排序,然后是当前的ID:

// XXX: Untested code
public int compare(TrackUserChanges tuc1, TrackUserChanges tuc2) {
    int cmp = tuc1.getId() - tuc2.getPreviousId();
    if (cmp == 0) {
       cmp = tuc1.getId() - tuc2.getId();
    }
    return cmp;
}

请注意,如果您使用Comparator,则应警惕与#equals的一致性。在你的情况下,这些将是不一致的,因为#equals应该将“like”字段比较为相等。请参阅java ComparatorSortedSet。来自比较者:

  

当且仅当c.compare(e1,e2)== 0具有与e1.equals(e2)相同的布尔值时,比较器c对一组元素S施加的排序被认为与equals一致。对于S中的每个e1和e2。

     

当使用能够强加与equals不一致的排序的比较器来排序有序集(或有序映射)时,应该小心。假设带有显式比较器c的有序集(或有序映射)与从集合S中绘制的元素(或键)一起使用。如果由S对S施加的排序与equals不一致,则排序集(或有序映射)将表现得“奇怪”。特别是有序集(或有序映射)将违反集合(或映射)的一般契约,它以等于的方式定义。

因此,如果您打算使用已排序的集合,则无法使用Comparator。您可以选择按#previousId然后id排序,如下所示:

// XXX: Untested code
public int compare(TrackUserChanges tuc1, TrackUserChanges tuc2) {
    int cmp = tuc1.getPreviousId() - tuc2.getPreviousId();
    if (cmp == 0) {
       cmp = tuc1.getId() - tuc2.getId();
    }
    return cmp;
}

这只会通过前一个id(然后是id)自然排序。所以,对于:

TrackUserChanges t = new TrackUserChanges(2,1);    //id, previousId
TrackUserChanges t1 = new TrackUserChanges(3,1);
TrackUserChanges t2 = new TrackUserChanges(1,1);

你仍会得到:     t2,t,t1

有关:

TrackUserChanges t3 = new TrackUserChanges(5,2);    //id, previousId
TrackUserChanges t4 = new TrackUserChanges(6,2);
TrackUserChanges t5 = new TrackUserChanges(7,1)

你会得到(按previousId然后id排序):     (previousId = 1)t2,t,t1,t5,     (previousId = 2)t3,t4

这样您就可以实现一致的compareTo#equals,以便在SortedSetTreeMap中使用。