2012-10-09 48 views
1

我有一個問題,我需要根據某些條件更改排序集的可比較值。Java設置奇怪的行爲

做這樣的事情:

SortedSet<T> groups; 

for(T t: groups){ 
     t.setOrdinal(max); 
} 

不會自動重新排列的SortedSet。

在線閱讀我發現我需要從集合中刪除對象,然後再次添加它。顯然,我不能在迭代集合的時候這樣做。所以我決定製作一套Arraylist。使集合爲空,然後再次添加所有元素,以便它們遵循排序的順序。 我做了這樣的事情:

SortedSet groups;

List<T> groupList = new ArrayList<T>(groups); 
groups = null; 
for(T t: groupList){ 
     t.setOrdinal(max); 
} 

groups = new TreeSet<T>(groupList); 

但是,當我檢查組設置它沒有遵循基於比較的排序順序,其比較的物品T

的序但當我是這樣的:

SortedSet的羣體;

List<T> groupList = new ArrayList<T>(groups); 
groups.clear(); 
for(T t: groupList){ 
     t.setOrdinal(max); 
} 

groups.addAll(groupList); 

我得到了預期的結果。有人能解釋我發生了什麼事嗎?

這是怎麼了我已經實現了我的T類

public class T implements Serializable, Comparable<T> { 
// 
int ordinal; 
//getter 
//setter 

@Override 
    public int compareTo(T that) { 
    if (that == null) { 
     return 1; 
    } 

    return this.ordinal - that.ordinal; 
    } 

} 

對於那些希望看到完整的程序:

List<SmartUser> groupsList = new ArrayList<SmartUser>(groups); 
groups = null; 
for (SmartUser smartUser : groupsList) { 
     if (smartUser.isExpired()) { 
       smartUser.setOrdinal(Long.MAX_VALUE); 
     } 
     SmartUserQuery smartUserQuery = smartUser.getSmartUserQuery(); 
     if (smartUserQuery != null) { 
       //Do parallel processing: of each samrtUser 
     } 
} 

groups = new TreeSet<SmartUser>groupsList; 

正確的結果給人的做法:

List<SmartUser> groupsList = new ArrayList<SmartUser>(groups); 
groups.clear(); 
for (SmartUser smartUser : groupsList) { 
     if (smartUser.isExpired()) { 
       smartUser.setOrdinal(Long.MAX_VALUE); 
     } 
     SmartUserQuery smartUserQuery = smartUser.getSmartUserQuery(); 
     if (smartUserQuery != null) { 
       //Do parallel processing: of each samrtUser 
     } 
} 

groups.addAll(groupsList); 

感謝。

+1

請顯示一個簡短的*完整*程序來展示問題。例如,我們不知道您的'SortedSet '是否使用了自定義比較器或正常的'Comparable '實現。 –

+0

從你提出的方式來看,這兩種方式都應該工作得很好。 – dasblinkenlight

+1

除了其他方面,您的'compareTo'方法由於溢出而中斷...並且您顯示的示例將*每個*值的序數設置爲相同的值,因此任何順序都是可接受的。再次,短,但完整的程序,請... –

回答

0

您的compareTo方法更改爲以下

@Override 
public int compareTo(CustomObject o) { 
    return Integer.valueOf(o.ordinal).compareTo(ordinal); 
} 

而且按TreeSet合同應提供的equals方法,這將是在同步與compareTo方法

@Override 
public boolean equals(Object obj) { 
    if (obj == null) 
     return false; 
    if (!(obj instanceof CustomObject)) 
     return false; 
    CustomObject o = (CustomObject) obj; 

    return this.ordinal == o.ordinal; 
} 

一個樣本實現

import java.util.ArrayList; 
import java.util.List; 
import java.util.Set; 
import java.util.TreeSet; 

public class CustomObject implements Comparable<CustomObject> { 

private int ordinal = 0; 

public CustomObject(int priority) { 
    this.ordinal = priority; 
} 

/** 
* @param args 
*/ 
public static void main(String[] args) { 

    List<CustomObject> list = new ArrayList<CustomObject>(); 
    list.add(new CustomObject(1)); 
    list.add(new CustomObject(2)); 
    list.add(new CustomObject(3)); 
    list.add(new CustomObject(6)); 
    list.add(new CustomObject(4)); 
    System.out.println("Before: " + list); 
    for (CustomObject object : list) { 
     if (object.ordinal == 4) { 
      object.ordinal = 10; 
     } 
    } 
    Set<CustomObject> set = new TreeSet<CustomObject>(); 
    set.addAll(list); 
    System.out.println("After: " + set); 

} 

@Override 
public int compareTo(CustomObject o) { 
    return Integer.valueOf(o.ordinal).compareTo(ordinal); 
} 

@Override 
public boolean equals(Object obj) { 
    if (obj == null) 
     return false; 
    if (!(obj instanceof CustomObject)) 
     return false; 
    CustomObject o = (CustomObject) obj; 

    return this.ordinal == o.ordinal; 
} 

@Override 
public String toString() { 
    return " Ordinal Value is :" + ordinal; 
} 

} 
+0

您確實需要重寫.equals方法,但這也意味着您應該重寫.hashcode方法,否則您的整個操作將會崩潰。哈希集使用內部哈希映射進行操作,如果.equals方法和.hashcode方法不一致(即無論使用何種字段確定相等性都需要成爲哈希碼生成的一部分),數據結構就會崩潰。在你的情況下,你可以將方法委託給Integer.valueOf(ordinal).hashcode() – Matt

+0

@Matt問題是關於TreeSet的,所以我現在包含hashCode,因爲散列只需要HashSet和HashMap。但是,這是好事,並且很容易添加。 –

+0

我認爲我的compareTo方法很好,因爲我確信序號永遠是非負的。 –

0

我發現我需要從集合中刪除對象,然後再添加它。顯然,我不能在迭代集合的時候這樣做。 所以我決定製作一套Arraylist。

看看我的回答maintaining TreeSet sort as object changes value並嘗試我的UpdateableTreeSet實施。它允許您在遍歷排序後的集合時執行延遲更新。