关于ArrayList的几个问题

时间:2012-11-10 18:04:43

标签: java arraylist

问题1:

指定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

有谁能告诉我如何锁定列表?

4 个答案:

答案 0 :(得分: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. 您需要提供更多背景信息。通常,当您在列表上执行某些操作时获取锁定会更有意义。

答案 1 :(得分:1)

  1. 如果列表很大,那么是的,声明初始大小是值得的。为什么?因为当你创建一个ArrayList时,它的初始大小通常是~10。当您添加新项目并且初始大小不够时,ArrayList会分配更多内存,并且所有元素都会重新定位,这需要花费时间。

  2. 不,这不是另一个线程所必需的。当您遍历列表并在循环体中添加或删除它的元素时,可能会发生此异常。然后你必须使用迭代器。

  3. 锁定列表是什么意思?您想要使其线程安全或禁用添加/删除其元素?在第二种情况下,您希望在unmodifiableCollection中使用java.util.Collections方法。

答案 2 :(得分:1)

Q1: 这就是ArrayList的样子

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

构造ArrayList时,会自动初始化数组的大小。当空间不足时,尺寸会自动调整为原始尺寸的1.5倍。

Q2: 你是完全正确的。 “例如,一个线程通常不允许修改Collection而另一个线程正在迭代它。通常,在这些情况下迭代的结果是不确定的。一些Iterator实现(包括所有通用集合的实现)如果检测到这种行为,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

答案 3 :(得分: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) {
       // ...
     }