如何解决在 Java 中迭代列表的方法
三种循环形式几乎相同。增强的for
循环:
for (E element : list) {
. . .
}
根据Java
语言规范,在效果上与显式使用带有传统循环的迭代器相同。for
在第三种情况下,您只能通过删除当前元素来修改列表内容,并且只有通过remove
迭代器本身的方法才能这样做。使用基于索引的迭代,您可以以任何方式自由修改列表。但是,添加或删除当前索引之前的元素可能会导致循环跳过元素或多次处理相同的元素;进行此类更改时,您需要正确调整循环索引。
在所有情况下,element
都是对实际列表元素的引用。没有任何迭代方法会复制列表中的任何内容。的内部状态的变化element
总是会在列表中相应元素的内部状态中看到。
本质上,迭代列表只有两种方法:使用索引或使用迭代器。增强的 for 循环只是 Java 5
中引入的一种语法快捷方式,以避免显式定义迭代器的乏味。对于这两种风格,您可以使用for
,while
或do
while
块提出本质上微不足道的变化,但它们都归结为同一件事(或者,更确切地说,两件事)。
编辑:正如@iX3 在评论中指出的那样,您可以ListIterator
在迭代时使用 a
来设置列表的当前元素。您需要使用List#listIterator()
而不是List#iterator()
初始化循环变量(显然,必须将其声明为
aListIterator
而不是 a Iterator
)。
解决方法
作为 Java 语言的新手,我试图让自己熟悉可能遍历列表(或可能是其他集合)的所有方式(或至少是非病态的方式)以及每种方式的优缺点。
给定一个List<E> list
对象,我知道以下遍历所有元素的方法:
基本for
循环(当然,也有等价的while
/do
while
循环)
// Not recommended (see below)!
for (int i = 0; i < list.size(); i++) {
E element = list.get(i);
// 1 - can call methods of element
// 2 - can use 'i' to make index-based calls to methods of list
// ...
}
注意:正如@amarseillan 指出的那样,这种形式对于迭代List
s
来说是一个糟糕的选择,因为该get
方法的实际实现可能不如使用Iterator
. 例如,LinkedList
实现必须遍历 i
之前的所有元素以获得第 i 个元素。
在上面的示例中,List
实现无法“保存其位置”以使未来的迭代更高效。对于
aArrayList
这并不重要,因为复杂性/成本get
是常数时间(O(1)),而对于 aLinkedList
它与列表的大小成正比(O(n))。
有关内置Collections
实现的计算复杂性的更多信息,请查看这个问题。
增强的 for循环
for (E element : list) {
// 1 - can call methods of element
// ...
}
迭代器
for (Iterator<E> iter = list.iterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// ...
}
for (ListIterator<E> iter = list.listIterator(); iter.hasNext(); ) {
E element = iter.next();
// 1 - can call methods of element
// 2 - can use iter.remove() to remove the current element from the list
// 3 - can use iter.add(...) to insert a new element into the list
// between element and iter->next()
// 4 - can use iter.set(...) to replace the current element
// ...
}
函数式 Java
list.stream().map(e -> e + 1); // Can apply a transformation function for e
Iterable.forEach,
Stream.forEach,…
(来自 Java 8 的 Stream API 的 map 方法(参见@i_am_zero 的答案)。)
在 Java 8 中,实现Iterable
(例如,所有List
s)的集合类现在有一个forEach
方法,可以用来代替上面演示的for
循环语句。
Arrays.asList(1,2,3,4).forEach(System.out::println);
// 1 - can call methods of an element
// 2 - would need reference to containing object to remove an item
// (TODO: someone please confirm / deny this)
// 3 - functionally separates iteration from the action
// being performed with each item.
Arrays.asList(1,4).stream().forEach(System.out::println);
// Same capabilities as above plus potentially greater
// utilization of parallelism
// (caution: consequently,order of execution is not guaranteed,// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this).
如果有的话,还有哪些其他方法?
(顺便说一句,我的兴趣根本不是出于优化性能的愿望;我只是想知道作为开发人员可以使用哪些形式。)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。