这是我的目标:
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
答案 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 Comparator和SortedSet。来自比较者:
当且仅当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
,以便在SortedSet
和TreeMap
中使用。