Java 排序对象比较

Java 排序对象比较,java,object,comparator,comparable,Java,Object,Comparator,Comparable,这是我的目标: public class TrackUserChanges{ private Long id; private Long previous; } 我有一个ArrayList。我想对对象进行如下排序: -若一个对象的getPrevious()等于另一个对象的getId,则将第一个对象(即具有该值的对象)放在getId()上 我在类中已经有一个compareTo方法,我不想破坏它。所以我创建了一个方法: public int compareTrack(TrackUs

这是我的目标:

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,你要做的不是一个好主意

请阅读合同中的
compareTo()

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

实施者还必须确保关系是可传递的: ((比较(x,y)>0)和&(比较(y,z)>0))意味着比较(x,z)>0

最后,实现者必须确保compare(x,y)==0意味着 所有z的sgn(比较(x,z))==sgn(比较(y,z))

如果你有
a(1,2)
b(2,1)
,它们不会是自反的:a.compareTo(b)和
b.compareTo(a)
都返回相同的符号,这违反了第一条规则

您还没有想到如何处理
a(1,2)
b(3,4)
之间的比较。我怀疑你是否能使它具有及物性和反身性


告诉我们你为什么需要这样做,也许有更好的选择。

你必须比较类似的东西

    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进行比较,即使它们都是长值。

您可以按如下方式使用
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;
}
但请注意,如果您确实使用了
比较器
,则应注意与
#equals
的一致性。在您的情况下,这些将是不一致的,因为
#equals
应将“like”字段比较为相等。见和。来自比较国:

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

当使用比较器时,应谨慎使用,比较器能够对排序集(或排序映射)施加与等于不一致的排序。假设一个带有显式比较器c的排序集(或排序映射)与从集合S中提取的元素(或键)一起使用。如果c对S施加的顺序与equals不一致,则排序集(或排序映射)的行为将“奇怪”。特别是排序集(或排序映射)将违反集合(或映射)的一般约定,它的定义是平等的

因此,如果计划使用已排序的集合,则不能使用
Comparator
。您是否可以选择按
#以前的id
然后按
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

用于:

您将获得(按
previousId
排序,然后按
id
排序): (以前的ID=1)t2,t,t1,t5, (以前的ID=2)t3,t4


这将使您能够实现一个一致的
比较,以
#equals
用于
SortedSet
TreeMap

我不理解“将第一个对象和具有该值的对象放在getId()上”这一部分。我想您要做的是
this.getPrevious().getId()==o.getId()
;不假设Id是基元。您还可以创建一个比较器,它将保存
compareTrack
排序逻辑。@Smutje我想以这样一种方式排序,即我将在getPrevious()中找到的Id放在第一位。示例:Id,previous 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
TrackUserChanges t3 = new TrackUserChanges(5,2);    //id, previousId
TrackUserChanges t4 = new TrackUserChanges(6,2);
TrackUserChanges t5 = new TrackUserChanges(7,1)