2012-01-19 31 views
7

外新增項目想知道是否有一個項目比現在的規模更大的位置添加到Java的ArrayList的一個有效的方法:Java的ArrayList的電流大小

場景:

ArrayList<Item> items = new ArrayList<Item>; 
    ... let's say I add three elements 

現在我想在10位(從剩下3項10爲空)

items.add(10,newItem); // item.size() == 3 

是否有一個有效的方式改變尺寸/填充空的ArrayList添加項目? 。

Java的實現使得大小字段私人:-(

+0

您應該改爲使用HashMap或SortedMap。 –

+0

好吧,使用Map不是內存中毒的解決方案,我們知道最後的結構是完整的 - > TIntObjectHashMap(trove)也許 – ic3

+0

HashMap不支持順序。 SortedMap是一個更好的選擇。 –

回答

6

恕我直言,你能做的最好的事情是items.addAll(Collections.nCopies(6, null))和希望,ArrayList實現了一些行爲,以便內部緊固這個

+0

這很好,但從性能的角度來看有點可怕 – ic3

+0

well nCopies只產生一個數組的列表包裝器,這樣你的ArrayList可以使用系統.arraycopy填充空值取決於它是如何實現的智能 – Hachi

+1

public boolean addAll(Collection c){ \t Object [] a = c.toArray(); int numNew = a.length; \t ensureCapacity(size + numNew); //增量modCount 系統。arraycopy(a,0,elementData,size,numNew); size + = numNew; \t return numNew!= 0; } – ic3

-2

使用構造ArrayList(int initialCapacity)這種方式,你可以設置一個初始容量

+1

InitialCapacity不是一個大小 - >線程「main」中的異常java.lang.IndexOutOfBoundsException:索引:9,大小:0 – ic3

+0

嘗試:public static void main(String [] args) { ArrayList list = new ArrayList(10); list.add(9,3); } – ic3

0

我會考慮在這裏使用SortedMap而不是List。這將允許索引不存在:

SorteMap<Integer, Item> myMap = new TreeMap<Integer, Map>(); 
int i=0; 
myMap.put(i++, first); 
myMap.put(i++, second); 
myMap.put(i++, third); 
myMap.put(10, other); 

如果一個地圖確實無法正常工作,如您所述。然後我會建議圍繞ArrayList創建一個裝飾器。在插入方法中,添加空值以填充空白位置。我建議使用番石榴的ForwardingList來緩解課堂的創作。這樣你只需要實現一種方法。

+0

這不是記憶中毒的選擇...... – ic3

+0

這裏的記憶有什麼問題? @John B - 更正此代碼。 –

+0

帶有1mio Object的TreeMap很大。 – ic3

0

不,你不能這樣做,但 如果你想這樣做,那麼在剩餘的指標,如添加空對象..

ArrayList<Object> items = new ArrayList<Object>(); 
    items.add(new Object()); 
    items.add(new Object()); 
    items.add(new Object()); 
    items.add(3,new Object()); 
+0

實際上我正在追求一些更優雅的東西:-) – ic3

2

這個怎麼樣?

ArrayList<Item> items = new ArrayList<Item>(); 

items.add(new Item(0)); 
items.add(new Item(1)); 
items.add(new Item(2)); 

items.addAll(Collections.<Item>nCopies(7, null)); 
items.add(10,new Item(10)); 

System.out.println(items); 

打印

[0, 1, 2, null, null, null, null, null, null, null, 10] 
+0

使用'10 - items.size'而不是'7'作爲更強大的選項。 –

0

如果存儲器和索引是如此重要,以至於使用普通陣列。

當它變得小使用System.arraycopy多數民衆贊成的方式ArrayList它的內部。

-

即使你使用ArrayList和有一百萬的對象,建議使用的ArrayList(INT參數:initialCapacity)-Constructor避免大量複製操作的

1

TreeMap的使用代替。這裏是檢查memony消費的簡單例子。分開運行第一次和第二次測試,並使用jvisualvm檢查堆大小。請記住多次執行GC。

public class Test { 


      public static void main(String[] args) throws InterruptedException { 
       String s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque metus."; 


       //Test 1 
       ArrayList<String> l = new ArrayList<String>(); 

       for (int i = 0; i < 1000000; i++) { 
        l.add(s + " " + i); 
        l.addAll(Collections.nCopies(i % 10, (String)null)); //Add some nulls 
       } 
       //Heap is > 5MB 

       //Test 2 uncomment and comment test 1 
    //   SortedMap<Integer, String> map = new TreeMap<Integer, String>(); 
    //   for (int i = 0; i < 1000000; i++) { 
    //    map.put(i,s + " " + i); 
    //   } 
       //Heap is < 5MB 

       Thread.sleep(100000); 

      } 
    } 

它看起來像TreeMap版本比ArrayList版本更少的內存消耗。自行檢查。

+0

彼得,ArrayList是一個數組,只是更多。完整數組如何可能比其他結構體積更大? ...我認爲你的例子有一個問題(我確定) – ic3

+0

我們正在談論一個完整的數組.. – ic3

+0

該數組是(s - 字符串,n - 空):snsnnsnnnsnnnnsnnnnns nnnnnnsnnnnnnns ...等有很多的內存保留爲引用,但設置爲空。 TreeMap沒有這個問題。正如你所說,這是一個數組。即使是1mio的空數組仍然需要內存。這一切都是關於你的名單如何「密集」。 –

0

@ icCube-你說的那個列表應該大概90%滿了。 我對這個解決方案的想法是:

  • 如果你確切地知道目標大小 - 使用普通陣列
  • 如果你知道目標的大小 - 使用ArrayList以儘可能接近目標大小初始容量。正如人們所說的那樣,用l.addAll(Collections.nCopies(n, (String)null));作爲空值。
  • 如果你不知道目標大小 - 你的ArrayList將被重新調整大小。調整大小意味着複製整個底層數組(它使用Arrays.copyOf)。你可以想象如果數組被複制 - 會發生什麼 - GC有很多工作。然後使用TreeMap。