2010-03-18 10 views
1

我一直在工作一整天,而且我無法弄清楚這可能是一件容易的任務 - 可能是缺少咖啡。 。
具有對象的Java列表 - 如果具有某個屬性的對象已經存在,則查找並替換(刪除)條目

我有一個synchronizedList其中一些對象正在存儲。這些對象有一個field這就像一個ID。這些對象攜帶關於用戶的信息和他的當前狀態(簡化)。

重點是,我只想爲每個用戶一個對象。所以當這個用戶的狀態發生變化時,我想刪除舊的條目並在List中保存一個新條目。

protected static class Objects{ 
    ... 
    long time; 
    Object ID; 
    ... 
    } 

...

if (Objects.contains(ID)) { 
      Objects.remove(ID); 
      Objects.add(newObject); 
     } else { 
      Objects.add(newObject); 
     } 

顯然,這不是去,但應該說明我正在尋找...
的方式也許數據結構是不是最適合這種目的,但任何幫助,歡迎!


編輯:
增加了一些信息...
一個 Set並沒有真正似乎適合我的目的。 Objects存儲除了一直改變的ID以外的一些其他字段。目的是,該列表將以某種方式代表用戶的最新活動。我只需要跟蹤最後的狀態,只保留描述這種情況的那個對象。
我想我會嘗試重新安排我的代碼有 Map,看看是否能工程...

+0

是的,Set的add方法在您的情況下是個問題。與地圖祝你好運! – extraneon 2010-03-18 14:51:43

+0

感謝,它的工作就像一個魅力 - 在HashMap上的「僞迭代」是有點iffy,但也適用於:-) – Gnark 2010-03-18 15:45:11

回答

0

地圖是最簡單的,但一個集合更好地反映你的邏輯。在那種情況下,我會建議一個Set。

根據數據對象的equals和hashCode,有兩種使用set的方法。

如果YourObject已經使用ID對象來確定equals(並且hashCode服從契約),那麼可以使用任何你想要的Set,那麼HashSet可能是最好的。

如果YourObjects業務邏輯需要不同的等號,並考慮ID字段旁邊的多個字段,則應使用自定義比較器。 TreeSet是一個可以使用這種比較器的Set。

一個例子:

Comparator<MyObject> comp = new Comparator<MyObject>{ 
    public int compare(MyObject o1, MyObject o2) { 
    // NOTE this compare is not very good as it obeys the contract but 
    // is not consistent with equals. compare() == 0 -> equals() != true here 
    // Better to use some more fields 
    return o1.getId().hashCode() < o2.getId().hashCode(); 
    } 
    public boolean equals(Object other) { 
    return 01.getId().equals(o2.getId()); 
    } 
} 

Set<MyObject> myObjects = new TreeSet(comp); 

EDIT 我已經更新上述代碼,以反映該ID不是int,由問題的建議。

+0

也許我過度簡化了問題,因爲ID是Object本身... – Gnark 2010-03-18 14:16:47

+0

@Sophomore更新了答案 – extraneon 2010-03-18 14:28:46

+0

爲什麼使用對象的哈希碼進行比較?這是錯誤的。 – 2010-03-18 16:07:38

1

而且你不能使用Set有隻有第一個存儲?

因爲它基本上正是你所需要的。

+1

如果一個對象的實例有其他屬性(除了ID),那麼他不需要第一個一個存儲,但最新的一個具有相同的ID值。 – Dan 2010-03-18 14:05:01

1

您可以使用HashSet來存儲對象,然後覆蓋HashSet將包含的類中的hashCode方法,以返回識別字段的哈希碼。

0

我的第一選擇將是一個HashSet的,這將要求您覆蓋的hashCode等於方法(不要忘了:如果你重寫一個,覆蓋一貫的除外)使物體與相同的ID字段被認爲是相等的。

但是,如果這個假設不是在你的應用程序的其他部分進行的,這可能會破壞一些東西。在這種情況下,您可以選擇使用HashMap(以ID爲關鍵字)或實現您自己的MyHashSet類(由此類HashMap支持)。

+0

如果你真的需要一個Set,那麼也可以使用帶有比較器的TreeSet,並且可能更適合模型。 – extraneon 2010-03-18 14:56:49

3

您可以使用HashMap(或者LinkedHashMap/TreeMap,如果順序很重要)使用ID和Object的值。隨着仿製藥,這將是HashMap<Object, Objects>();

然後你可以使用

if (map.containsKey(ID)) { 
    map.remove(ID); 
} 

map.put(newID, newObject); 

或者,您可以繼續使用名單,但我們不能只是修改集合在迭代,所以我們可以將使用迭代器刪除現有項目,然後在循環外添加新項目(現在您確定舊項目已消失):

List<Objects> syncList = ... 

for (Iterator<Objects> iterator = syncList.iterator(); iterator.hasNext();) { 
    Objects current = iterator.next(); 

    if (current.getID().equals(ID)) { 
     iterator.remove(); 
    } 
} 

syncList.add(newObject); 
相關問題