java - 如何在Java中迭代时在List中添加元素?

Posted

技术标签:

【中文标题】java - 如何在Java中迭代时在List中添加元素?【英文标题】:How to add element in List while iterating in java? 【发布时间】:2012-06-26 00:01:23 【问题描述】:

假设我有一个类似的列表:

List<String> list = new ArrayList<>();
list.add("a");
list.add("h");
list.add("f");
list.add("s");

在遍历此列表时,我想在列表末尾添加一个元素。但我不想遍历新添加的元素,我想迭代到列表的初始大小。

for (String s : list)
     /* Here I want to add new element if needed while iterating */

谁能建议我如何做到这一点?

【问题讨论】:

【参考方案1】:

您不能为此使用 foreach 语句。 foreach 在内部使用了一个迭代器:

这个类的迭代器和listIterator返回的迭代器 方法是快速失败的:如果列表在任何结构上被修改 迭代器创建后的时间,除了通过 迭代器自己的删除或添加方法,迭代器会抛出一个 ConcurrentModificationException。

(来自 ArrayList javadoc)

在 foreach 语句中,您无权访问迭代器的 add 方法,并且无论如何这仍然不是您想要的 add 类型,因为它不会在末尾追加。您需要手动遍历列表:

int listSize = list.size();
for(int i = 0; i < listSize; ++i)
  list.add("whatever");

请注意,这仅对允许随机访问的列表有效。您可以通过检查列表是否实现 RandomAccess 标记接口来检查此功能。 ArrayList 具有随机访问权限。链表没有。

【讨论】:

【参考方案2】:

遍历列表的副本并将新元素添加到原始列表中。

for (String s : new ArrayList<String>(list))     

    list.add("u");

看 How to make a copy of ArrayList object which is type of List?

【讨论】:

【参考方案3】:

只需迭代老式方式,因为您需要显式索引处理:

List myList = ...
...
int length = myList.size();
for(int i = 0; i < length; i++) 
   String s = myList.get(i);
   // add items here, if you want to

【讨论】:

不,不会。它会在使用迭代器并在迭代时添加元素时,但在您自己进行迭代时不会。 OPs 想要“迭代到初始大小”。【参考方案4】:

您可以迭代原始列表的副本(克隆):

List<String> copy = new ArrayList<String>(list);
for (String s : copy) 
    // And if you have to add an element to the list, add it to the original one:
    list.add("some element");

请注意,在对列表进行迭代时甚至不可能将新元素添加到列表中,因为这将导致 ConcurrentModificationException

【讨论】:

【参考方案5】:

我通过将元素添加到一个新的空 tmp 列表中,然后使用 addAll() 将 tmp 列表添加到原始列表中来做到这一点。这可以防止不必要地复制大型源列表。

想象一下当 OP 的原始列表中有几百万个项目时会发生什么;有一段时间你会吸收两倍的内存。

除了节省资源之外,这种技术还可以防止我们不得不求助于 80 年代风格的 for 循环和使用在某些情况下可能没有吸引力的有效数组索引。

【讨论】:

【参考方案6】:

为了帮助解决这个问题,我创建了一个函数来更容易实现它。

public static <T> void forEachCurrent(List<T> list, Consumer<T> action) 
    final int size = list.size();
    for (int i = 0; i < size; i++) 
        action.accept(list.get(i));
    

例子

    List<String> l = new ArrayList<>();
    l.add("1");
    l.add("2");
    l.add("3");
    forEachCurrent(l, e -> 
        l.add(e + "A");
        l.add(e + "B");
        l.add(e + "C");
    );
    l.forEach(System.out::println);

【讨论】:

以上是关于java - 如何在Java中迭代时在List中添加元素?的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用Java 8运行时在流中获取新用户输入

如何在java中实现List集合的遍历

JAVA中的泛型用法一种: <T> 返回值用法。

Java中Set集合怎样用for遍历?

在列表迭代期间从 java.util.List 中删除元素时引发 ConcurrentModificationException? [复制]

java 迭代