[英]Java ArrayList add item outside current size
Wondering whether there is an efficient way to add an item to Java's ArrayList at a bigger position than its current size: 想知道是否有一种有效的方法将项目添加到Java的ArrayList中,其位置比当前大小更大:
Scenario: 场景:
ArrayList<Item> items = new ArrayList<Item>;
... let's say I add three elements
Now I would like to add an item at position 10 (leaving items from 3 to 10 to null) 现在我想在位置10添加一个项目(将项目从3到10保留为null)
items.add(10,newItem); // item.size() == 3
Is there an efficient way resizing/filling an ArrayList with nulls? 是否有一种有效的方法可以使用null调整/填充ArrayList?
Java's implementation makes size field private :-(.. Java的实现使大小字段私有:-( ..
你可以做的最好的事情是items.addAll(Collections.nCopies(6, null))
并希望,ArrayList实现了一些内部紧固的行为
How about this? 这个怎么样?
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);
prints 版画
[0, 1, 2, null, null, null, null, null, null, null, 10]
This is an older question, but you can now use SparseArray
as an (almost) direct drop-in replacement for ArrayList
. 这是一个较旧的问题,但您现在可以使用
SparseArray
作为ArrayList
的(几乎)直接替代品。 It allows non-contiguous integer key values, and returns null if a value has not been set for a key. 它允许非连续的整数键值,如果没有为键设置值,则返回null。 Performance-wise it was designed exactly for your needs.
性能方面,它的设计完全符合您的需求。 Instead of
add
you use append
, which is more descriptive in that you are appending to the end of whatever the max key is, even if there is gaps. 而不是
add
你使用append
,这更具描述性,因为即使存在间隙,你也会附加到max key的末尾。 You can also set
at any key value you'd like, even if it is beyond the maximum key. 您也可以
set
任何您想要的键值,即使它超出了最大键值。
Use TreeMap instead. 请改用TreeMap。 Here is simple example to check memony consuption.
这是检查和谐消耗的简单例子。 Run first and second test separatly and use jvisualvm to check heap size.
分别运行第一个和第二个测试并使用jvisualvm检查堆大小。 Remember to Perform GC several times.
请记住多次执行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);
}
}
It looks like TreeMap
version is even less memory consuming than ArrayList version. 看起来
TreeMap
版本比ArrayList版本的内存消耗更少。 Check yourself. 自行检查。
No, you can't: 不,你不能:
http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html#add(int , E) http://docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html#add(int,E )
Throws: IndexOutOfBoundsException - if the index is out of range (index < 0 || index > size())
抛出:IndexOutOfBoundsException - 如果索引超出范围(索引<0 || index> size())
I would consider using a SortedMap instead of a List here. 我会考虑在这里使用SortedMap而不是List。 This will allow for indexes to not exist:
这将允许索引不存在:
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);
If a Map truly will not work, as you stated. 如果你说的话,地图真的不起作用。 I would then suggest creating a Decorator around ArrayList.
然后我会建议在ArrayList周围创建一个Decorator。 In the insert method, add nulls to fill the empty locations.
在insert方法中,添加空值以填充空位置。 I would suggest using Guava's ForwardingList to ease the creation of the class.
我建议使用Guava的ForwardingList来简化类的创建。 This way you would only have to implement one method.
这样你只需要实现一个方法。
No, you can't do this, But if you wish to do that, then add empty object in remaining index such as.. 不,你不能这样做,但如果你想这样做,那么在剩余的索引中添加空对象,比如..
ArrayList<Object> items = new ArrayList<Object>();
items.add(new Object());
items.add(new Object());
items.add(new Object());
items.add(3,new Object());
If memory and index is so important that use a normal array. 如果内存和索引非常重要,那么使用普通数组。
When it becomes to small use System.arraycopy thats the way ArrayList does it internal. 当它变得很小时使用System.arraycopy就像ArrayList在内部做的那样。
-- -
Even if you use the ArrayList and have a Million Objects it is advisable to use the ArrayList(int initialCapacity)-Constructor to avoid a lot of copy-operations 即使你使用ArrayList并拥有一个Million Objects,建议使用ArrayList(int initialCapacity)-Constructor来避免大量的复制操作
@icCube- you said, that list should be about 90% full. @ icCube-你说,那个名单应该是90%左右。 My idea for this solution is:
我对这个解决方案的想法是:
l.addAll(Collections.nCopies(n, (String)null));
l.addAll(Collections.nCopies(n, (String)null));
放在一起l.addAll(Collections.nCopies(n, (String)null));
as people said. Use constructor ArrayList(int initialCapacity)
. 使用构造函数
ArrayList(int initialCapacity)
。 This way you can set an initial capacity. 这样您就可以设置初始容量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.