2011-05-26 61 views
9

我有一個問題。當我嘗試將「相同」對象兩次添加到ArrayList時發生了什麼。對於「相同」,我的意思是一個單獨的類的對象,它被標識爲與equals()和hashCode()相同。它對於大多數成員變量具有不同的值,並且可能是由不同的線程創建的,但對於equals()和hashCode()它是「相同的」。 第二個對象是否替換第一個對象?ArrayList - 添加「相同」的對象(same => equals,hashCode),線程

此外,如果兩個線程嘗試將這些對象同時完全添加到ArrayList會發生什麼?這甚至有可能嗎?如果是,會發生什麼?

謝謝! :-)

[編輯]感謝所有的答案!我應該使用synchronizedList,而不是使用「synchronize(list){}」? - >我讀了文檔,甚至與synchronizedList,迭代同步(列表)將被使用

[EDIT2] 一個synchronizedList可以被聲明爲成員變量嗎?我嘗試了,但它沒有奏效。

回答

12

不,ArrayList根本不會嘗試檢測到重複 - 您可以有一個ArrayList具有完全相同的參考多次出現。如果你想要一個集合避免重複,你需要一個Set的實現 - 如果你想要保留廣告訂單,你可能想要LinkedHashSet

但是,請注意,不鎖定ArrayList應該而不是首先從多個線程中突變 - 它並不意味着以這種方式是一個線程安全的集合。有幾個線程可以ArrayList讀取而不同步,但不能對它進行變異。從文檔:

請注意,此實現不同步。如果多個線程同時訪問ArrayList實例,並且至少有一個線程在結構上修改了列表,則它必須在外部同步。 (結構修改是任何添加或刪除一個或多個元素的操作,或明確調整後備數組的大小;僅設置元素的值不是結構修改。)這通常通過同步某些自然封裝名單。如果不存在這樣的對象,則應使用Collections.synchronizedList方法「列出」列表。這是在創建時最好的做法,以防止列表

意外的不同步訪問,如果你想從變異多線程的集合而不鎖,我建議你看看java.util.concurrent集合。

4

它將允許簡單添加。名單與hashCode()equals()無關,而插入它不關心重複。

ArrayList不是線程安全的,因此您可能無法獲得期望的結果。您可以有synchronizedListCollections

2

ArrayList可以包含對同一個確切對象(身份等價)的多個引用。添加對象時,它不檢查equals()hashCode()

您將在ArrayList中結束兩個引用。

ArrayList不是線程安全的......所以如果您嘗試在同一時間添加兩個線程的行爲是未定義的。如果你想做那樣的事情,也許試試用SynchronizedList

6

第二個對象是否將第一個對象替換爲 ?

沒有,大部分開發商做明確的檢查

if(!list.contains(foo)){ 
    list.add(foo); 
} 

此外,如果兩個線程試圖 正好在 同時ArrayList中添加這些對象會發生什麼?這個 甚至可能嗎?如果是,會發生什麼?

是的,這是可能的。如果多個線程寫入/來自同一ArrayList閱讀,然後用​​關鍵字,只要你進入這個名單

public List<Foo> getFoos(){ 
    synchronized(list){ 
     return list; 
    } 
} 

public void addFoo(Foo foo){ 
    synchronized(list){ 
     list.add(foo); 
    } 
} 

編輯

正如有人指出的那樣,我想確認是否在ArrayList包含要添加的對象非常昂貴。如果你想確保只添加一次對象,我會遵循下面的建議使用LinkedHashSet。根據API,試圖add到該數據結構它

當將指定的元素將其設置 ,如果它不是已存在。如果該集合不包含 元素e2(e == null? e2 == null:e.equals(e2)),則正式添加指定元素e 。如果此集合 已包含該元素,則呼叫 會使該集合保持不變並返回 false。

+0

-1每個對'ArrayList.contains'的調用都是O(n)。這是創建獨特列表的一種可怕方式。 'LinkedHashSet'對此更好。 – 2011-05-26 12:24:49

+0

但是當使用LinkedHashSet訪問它時必須同步,是否正確?那爲什麼不使用synchronizedList呢? – nano7 2011-05-26 12:45:55

+0

@ nano7,當然它必須是同步的。僅僅因爲您更改了收集並不意味着您更改了同步策略。你可以自由地使用你想要的任何同步數據結構,但是如果你打算使用'LinkedHashSet',我建議使用'synchronizedSet'。 – mre 2011-05-26 12:53:01

1

如果您嘗試添加同一個對象兩次,它將工作,或者如果您嘗試添加2個對象的所有內容都一樣,它仍然可以工作。這不是最好的做法,因爲它難以保持清單。

整體:你不應該這樣做

相關問題