对于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
实现没有办法“保存其位置”以使将来的迭代更加有效。对于a而言,ArrayList
这并不重要,因为的复杂度/成本get
是恒定时间(O(1)),而对于a而言LinkedList
,它的复杂度/成本与列表的大小(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
// ...
}
ListIterator
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
(例如,all List
)现在具有一个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,2,3,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).
还有什么其他方式(如果有)?
(顺便说一句,我的兴趣根本不是出于优化性能的渴望;我只是想知道开发人员可以使用哪些形式。)
List
接口的问题吗?