2012-11-10 14 views
5

問題1幾個問題:上的ArrayList

是否有意義specifiy ArrayList的大小。我知道列表中會包含多少元素,事先指定大小還是不重要的。

List<String> list = new ArrayList<String>(1); 
list.add("Hello"); 

List<String> newList = new ArrayList<String>(); 
newList.add("Hello"); 

問題2:

,當你操作(添加,刪除)的集合而遍歷同一集合時發生java.util.ConcurrentModificationException。 Does that mean there is a thread which is modifying the ArrayList and another Thread iterating the same object.

問題3

誰能告訴我怎樣可以鎖定一個列表?

回答

8
  1. 它很重要,如果你加入了很多的項目,因爲它意味着集合將不需要繼續複製其內部緩衝區,因爲它去一起。有了一個小列表,它不會有太大的區別。請注意,你不指定大小ArrayList - 你指定的初始容量

    List<String> list = new ArrayList<String>(10000); 
    System.out.println(list.size()); // 0 
    

    你仍然需要將項目添加到它改變大小 - 但你可以添加項目在需要執行內部複製之前達到其容量。

  2. 不,不需要涉及額外的線程。這意味着你在迭代它的時候修改了集合。這可以很容易在一個單獨的線程:

    for (String item : items) { 
        items.add("Foo"); // The next iteration step will fail. 
    } 
    
  3. 你需要給予更多的上下文。通常,在列表上執行某些操作時,獲取鎖定會更有意義。

+0

@halex:修正,謝謝。 –

1
  1. 如果列表會很大,那麼是值得聲明的初始大小。爲什麼?因爲當你創建一個ArrayList時,它的初始大小通常是~10。當你添加新項目並且初始大小不夠時,ArrayList會分配更多的內存,並且所有元素都會重新定位,這需要花費一些時間。

  2. 不,它不是必需的另一個線程。當您迭代列表並在循環體中添加或刪除它的元素時,可能會發生此異常。然後您可以使用迭代器。

  3. 你是什麼意思的鎖定列表?你想讓它線程安全或禁用添加/刪除其元素?在第二種情況下,您想在java.util.Collections中使用unmodifiableCollection方法。

+2

1點,你不指定初始大小* * - 你指定的初始容量* *。即使容量巨大,size()在施工後仍然會返回0。 –

+0

對不起,我不是英語母語的人,我不知道我應該用'容量'這個詞。感謝您的通知! –

1

Q1: 這是ArrayList的可能是什麼樣子

public ArrayList{ 
    private int[] elementData; 
    private int size; 
} 

當你構建一個ArrayList,數組的大小自動初始化。當空間不足時,尺寸會自動調整爲原始尺寸的1.5倍。

Q2: 你完全正確。 「例如,一個線程通常不允許修改一個集合,而另一個線程正在迭代它。通常,在這些情況下迭代的結果是不確定的。一些迭代器實現(包括所有通用集合JRE提供的實現)可能會選擇拋出這個異常,如果檢測到這種行爲的話,那麼迭代器就稱爲快速迭代器,因爲它們會快速而乾淨地失敗,而不會在未確定的時間冒着任意的,非確定性的行爲在將來。」 -java DOC http://docs.oracle.com/javase/1.5.0/docs/api/java/util/ConcurrentModificationException.html

Q3: 要鎖定一個列表中,您使用

Collections.unmodifiableList(list); 

這適用於所有類別,並從改變數據禁止用戶。換句話說,它給用戶一個「只讀」副本。你可以在這裏閱讀更多關於集合類。 http://docs.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html

1

關於質詢號碼3: 有兩種方法來鎖定一個列表

1)隱式監視器鎖定:如果您使用集合的工廠方法創建一個同步的名單,那麼你可以使用包裝對象來創建鎖。

List<T> list = new ArrayList<T>(); 
    List<T> slist = Collections.synchronizedList(list); 
    synchoronized(slist) { 
    //code 
    } 

在這種情況下,slist將用於迭代過程中的鎖定和任何複合動作。

2)您可以使用Object類作爲鎖定

Object lock = new Object(); 
    synchronized (lock) { 
     // ... 
    }