在Java中,遍历列表的同时修改列表有多种方式,每种方式都有其适用的场景和优缺点。以下是几种常见的方法:
-
使用Iterator的remove()方法:
- 这是官方推荐的方式,可以在迭代过程中安全地删除元素,而不会抛出
ConcurrentModificationException
。 - 示例代码:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String element = iterator.next(); if (element.equals("B")) { iterator.remove(); } }
- 这是官方推荐的方式,可以在迭代过程中安全地删除元素,而不会抛出
-
使用CopyOnWriteArrayList:
- 这是一个线程安全的列表,允许在遍历的同时进行修改。在修改时会创建一个新的数组,迭代器在旧数组上遍历。
- 示例代码:
List<String> list = new CopyOnWriteArrayList<>(); list.add("A"); list.add("B"); list.add("C"); for (String element : list) { if (element.equals("B")) { list.remove(element); } System.out.println(element); }
-
从后往前遍历并删除元素:
- 通过手动管理索引,从后往前遍历列表,删除元素时不会影响前面元素的索引。
- 示例代码:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); for (int i = list.size() - 1; i >= 0; i--) { if (list.get(i).equals("B")) { list.remove(i); } }
-
使用并发集合:
- 如
ConcurrentLinkedQueue
等,设计上支持并发修改,适用于多线程环境。 - 示例代码:
ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>(); queue.add("A"); queue.add("B"); queue.add("C"); Iterator<String> iterator = queue.iterator(); while (iterator.hasNext()) { String element = iterator.next(); if (element.equals("B")) { queue.remove(element); } }
- 如
-
使用removeIf()等集合操作方法:
- 不是在传统迭代过程中修改,但可以达到类似效果。
- 示例代码:
List<String> list = new ArrayList<>(); list.add("A"); list.add("B"); list.add("C"); list.removeIf(element -> element.equals("B"));
选择哪种方式取决于具体的需求和场景。在单线程环境下,可以选择上述任何一种方式;在多线程环境下,可能需要更复杂的同步机制或选择线程安全的集合类。