AFAIK有两种方法:
例如,
List<Foo> fooListCopy = new ArrayList<Foo>(fooList); for(Foo foo : fooListCopy){ // modify actual fooList }
和
Iterator<Foo> itr = fooList.iterator(); while(itr.hasNext()){ // modify actual fooList using itr.remove() }
是否有任何理由偏爱一种方法(例如,出于可读性的简单原因而偏爱第一种方法)?
让我举几个例子,并提出一些避免方案ConcurrentModificationException。
ConcurrentModificationException
假设我们有以下藏书
List<Book> books = new ArrayList<Book>(); books.add(new Book(new ISBN("0-201-63361-2"))); books.add(new Book(new ISBN("0-201-63361-3"))); books.add(new Book(new ISBN("0-201-63361-4")));
收集并删除
第一种技术是收集所有要删除的对象(例如,使用增强的for循环),并在完成迭代后删除所有找到的对象。
ISBN isbn = new ISBN("0-201-63361-2"); List<Book> found = new ArrayList<Book>(); for(Book book : books){ if(book.getIsbn().equals(isbn)){ found.add(book); } } books.removeAll(found);
假设你要执行的操作是“删除”。
如果要“添加”此方法也可以,但是我认为你将遍历另一个集合,以确定要添加到第二个集合中的元素,然后addAll在最后发出一个方法。
使用ListIterator
如果要使用列表,则另一种技术是使用ListIterator,它支持在迭代过程中删除和添加项目。
ListIterator
ListIterator<Book> iter = books.listIterator(); while(iter.hasNext()){ if(iter.next().getIsbn().equals(isbn)){ iter.remove(); } }
同样,我在上面的示例中使用了“删除”方法,这似乎是你的问题所暗示的含义,但是你也可以add在迭代过程中使用其方法添加新元素。
使用JDK> = 8
对于使用Java 8或更高版本的用户,你可以使用多种其他技术来利用它。
你可以removeIf在Collection基类中使用新方法:
removeIf
Collection
ISBN other = new ISBN("0-201-63361-2"); books.removeIf(b -> b.getIsbn().equals(other));
或使用新的流API:
ISBN other = new ISBN("0-201-63361-2"); List<Book> filtered = books.stream() .filter(b -> b.getIsbn().equals(other)) .collect(Collectors.toList());
在后一种情况下,要从books = filtered集合中过滤元素,你可以将原始引用重新分配给过滤后的集合(即),或将过滤后的集合用于removeAll从原始集合中找到的元素(即books.removeAll(filtered))。
books = filtered
removeAll
books.removeAll(filtered)
使用子列表或子集
还有其他选择。如果列表已排序,并且要删除连续的元素,则可以创建一个子列表,然后清除它:
books.subList(0,5).clear();
由于子列表由原始列表支持,因此这将是删除此元素子集合的有效方法。
使用NavigableSet.subSet方法或那里提供的任何切片方法,可以通过排序集实现类似的效果。
NavigableSet.subSet
注意事项:
你使用哪种方法可能取决于你打算做什么
removeAl
Iterator
ListIterator/ Iterator
remove
Javadocs
UnsupportedOperationException