2012-01-19 27 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。