本文翻译自:Ways to iterate over a list in Java

Being somewhat new to the Java language I'm trying to familiarize myself with all the ways (or at least the non-pathological ones) that one might iterate through a list (or perhaps other collections) and the advantages or disadvantages of each. 对Java语言有些陌生,我试图使自己熟悉所有可能遍历列表(或其他集合)的方式(或至少是非病理性方式)以及每种方式的优缺点。

Given a List<E> list object, I know of the following ways to loop through all elements: 给定一个List<E> list对象,我知道以下遍历所有元素的方式:

Basic for loop (of course, there're equivalent while / do while loops as well) 基本的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// ...
}

Note: As @amarseillan pointed out, this form is a poor choice for iterating over List s, because the actual implementation of the get method may not be as efficient as when using an Iterator . 注意:正如@a​​marseillan指出的那样,这种形式对于迭代List是一个糟糕的选择,因为get方法的实际实现可能不如使用Iterator时高效。 For example, LinkedList implementations must traverse all of the elements preceding i to get the i-th element. 例如, LinkedList实现必须遍历i之前的所有元素才能获得第i个元素。

In the above example there's no way for the List implementation to "save its place" to make future iterations more efficient. 在上面的示例中, List实现无法“保存位置”以使将来的迭代更加有效。 For an ArrayList it doesn't really matter, because the complexity/cost of get is constant time (O(1)) whereas for a LinkedList is it proportional to the size of the list (O(n)). 对于一个ArrayList它其实并不重要,因为复杂性/成本get是恒定的时间(O(1)),而对于LinkedList是成正比的列表的大小(为O(n))。

For more information about the computational complexity of the built-in Collections implementations, check out this question . 有关内置Collections实现的计算复杂度的更多信息,请查看此问题 。

Enhanced for loop (nicely explained in this question ) 增强了for循环 ( 此问题对此做了很好的解释)

for (E element : list) {// 1 - can call methods of element// ...
}

Iterator 迭代器

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 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// ...
}

Functional Java 功能性Java

list.stream().map(e -> e + 1); // Can apply a transformation function for e

Iterable.forEach , Stream.forEach , ... Iterable.forEach , Stream.forEach ,...

(A map method from Java 8's Stream API (see @i_am_zero's answer).) (来自Java 8的Stream API的map方法(请参阅@i_am_zero的答案)。)

In Java 8 collection classes that implement Iterable (for example, all List s) now have a forEach method, which can be used instead of the for loop statement demonstrated above. 在实现Iterable Java 8集合类(例如,所有List )中,现在具有forEach方法,可以使用该方法代替上面演示的for循环语句 。 (Here is another question that provides a good comparison.) (这是另一个可以很好比较的问题。)

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).

What other ways are there, if any? 还有什么其他方式(如果有)?

(BTW, my interest does not stem at all from a desire to optimize performance ; I just want to know what forms are available to me as a developer.) (顺便说一句,我的兴趣根本不是出于优化性能的愿望;我只是想知道开发人员可以使用哪些形式。)


#1楼

参考:https://stackoom.com/question/1FFI3/遍历Java中的列表的方法


#2楼

You could always switch out the first and third examples with a while loop and a little more code. 您总是可以使用while循环和更多的代码切换出第一个和第三个示例。 This gives you the advantage of being able to use the do-while: 这为您提供了可以使用do-while的优势:

int i = 0;
do{E element = list.get(i);i++;
}
while (i < list.size());

Of course, this kind of thing might cause a NullPointerException if the list.size() returns 0, becuase it always gets executed at least once. 当然,如果list.size()返回0,则这种情况可能会导致NullPointerException,因为它总是至少执行一次。 This can be fixed by testing if element is null before using its attributes / methods tho. 这可以通过在使用元素的属性/方法之前测试元素是否为空来解决。 Still, it's a lot simpler and easier to use the for loop 尽管如此,使用for循环要简单得多


#3楼

I don't know what you consider pathological, but let me provide some alternatives you could have not seen before: 我不知道您认为病理是什么,但让我提供一些您之前从未见过的选择:

List<E> sl= list ;
while( ! sl.empty() ) {E element= sl.get(0) ;.....sl= sl.subList(1,sl.size());
}

Or its recursive version: 或其递归版本:

void visit(List<E> list) {if( list.isEmpty() ) return;E element= list.get(0) ;....visit(list.subList(1,list.size()));
}

Also, a recursive version of the classical for(int i=0... : 另外,经典的for(int i=0...的递归版本:

void visit(List<E> list,int pos) {if( pos >= list.size() ) return;E element= list.get(pos) ;....visit(list,pos+1);
}

I mention them because you are "somewhat new to Java" and this could be interesting. 我之所以提到它们,是因为您“对Java有点陌生”,这可能很有趣。


#4楼

Example of each kind listed in the question: 问题中列出的每种示例:

ListIterationExample.java ListIterationExample.java

import java.util.*;public class ListIterationExample {public static void main(String []args){List<Integer> numbers = new ArrayList<Integer>();// populates list with initial valuesfor (Integer i : Arrays.asList(0,1,2,3,4,5,6,7))numbers.add(i);printList(numbers);         // 0,1,2,3,4,5,6,7// replaces each element with twice its valuefor (int index=0; index < numbers.size(); index++) {numbers.set(index, numbers.get(index)*2); }printList(numbers);         // 0,2,4,6,8,10,12,14// does nothing because list is not being changedfor (Integer number : numbers) {number++; // number = new Integer(number+1);}printList(numbers);         // 0,2,4,6,8,10,12,14  // same as above -- just different syntaxfor (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {Integer number = iter.next();number++;}printList(numbers);         // 0,2,4,6,8,10,12,14// ListIterator<?> provides an "add" method to insert elements// between the current element and the cursorfor (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {Integer number = iter.next();iter.add(number+1);     // insert a number right before this}printList(numbers);         // 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15// Iterator<?> provides a "remove" method to delete elements// between the current element and the cursorfor (Iterator<Integer> iter = numbers.iterator(); iter.hasNext(); ) {Integer number = iter.next();if (number % 2 == 0)    // if number is even iter.remove();      // remove it from the collection}printList(numbers);         // 1,3,5,7,9,11,13,15// ListIterator<?> provides a "set" method to replace elementsfor (ListIterator<Integer> iter = numbers.listIterator(); iter.hasNext(); ) {Integer number = iter.next();iter.set(number/2);     // divide each element by 2}printList(numbers);         // 0,1,2,3,4,5,6,7}public static void printList(List<Integer> numbers) {StringBuilder sb = new StringBuilder();for (Integer number : numbers) {sb.append(number);sb.append(",");}sb.deleteCharAt(sb.length()-1); // remove trailing commaSystem.out.println(sb.toString());}
}

#5楼

The three forms of looping are nearly identical. 三种形式的循环几乎相同。 The enhanced for loop: 增强的for循环:

for (E element : list) {. . .
}

is, according to the Java Language Specification , identical in effect to the explicit use of an iterator with a traditional for loop. 根据Java语言规范 ,其作用与显式使用带有传统for循环的迭代器相同 In the third case, you can only modify the list contents by removing the current element, and then only if you do it through the remove method of the iterator itself. 在第三种情况下,您只能通过删除当前元素来修改列表内容,然后再通过迭代器本身的remove方法来进行操作。 With index-based iteration, you are free to modify the list in any way. 使用基于索引的迭代,您可以自由地以任何方式修改列表。 However, adding or removing elements that come before the current index risks having your loop skipping elements or processing the same element multiple times; 但是,添加或删除当前索引之前的元素可能会导致循环跳过元素或多次处理同一元素; you need to adjust the loop index properly when you make such changes. 进行此类更改时,您需要适当地调整循环索引。

In all cases, element is a reference to the actual list element. 在所有情况下, element都是对实际list元素的引用。 None of the iteration methods makes a copy of anything in the list. 没有一种迭代方法可以复制列表中的任何内容。 Changes to the internal state of element will always be seen in the internal state of the corresponding element on the list. element内部状态的更改将始终在列表中相应元素的内部状态中显示。

Essentially, there only two ways to iterate over a list: by using an index or by using an iterator. 本质上,只有两种方法可以遍历列表:使用索引或使用迭代器。 The enhanced for loop is just a syntactic shortcut introduced in Java 5 to avoid the tedium of explicitly defining an iterator. 增强的for循环只是Java 5中引入的语法快捷方式,以避免显式定义迭代器的繁琐工作。 For both styles, you can come up with essentially trivial variations using for , while or do while blocks, but they all boil down to the same thing (or, rather, two things). 对于这两种样式,您都可以使用forwhiledo while块提供一些琐碎的变体,但是它们全都归结为同一件事(或者说是两件事)。

EDIT: As @iX3 points out in a comment, you can use a ListIterator to set the current element of a list as you are iterating. 编辑:作为@ IX3在评论中指出,你可以使用ListIterator设置列表的当前元素为你迭代。 You would need to use List#listIterator() instead of List#iterator() to initialize the loop variable (which, obviously, would have to be declared a ListIterator rather than an Iterator ). 您将需要使用List#listIterator()而不是List#iterator()来初始化循环变量(显然,必须将其声明为ListIterator而不是Iterator )。


#6楼

A JDK8-style iteration: JDK8样式的迭代:

public class IterationDemo {public static void main(String[] args) {List<Integer> list = Arrays.asList(1, 2, 3);list.stream().forEach(elem -> System.out.println("element " + elem));}
}

遍历Java中的列表的方法相关推荐

  1. 遍历Java中的列表

    遍历Java中的列表 这篇文章将讨论在 Java 中迭代列表的各种方法. 1.使用 List.toString() 方法 如果我们只是想显示列表的内容,我们可以通过使用 toString() 方法,然 ...

  2. python创建列表_python创建与遍历List二维列表的方法

    python 创建List二维列表 lists = [[] for i in range(3)] # 创建的是多行三列的二维列表 for i in range(3): lists[0].append( ...

  3. python append函数二维_python创建与遍历List二维列表的方法

    python创建与遍历List二维列表的方法 python 创建List二维列表 lists = [[] for i in range(3)] # 创建的是多行三列的二维列表 for i in ran ...

  4. java中怎样克隆,如何在Java中克隆列表?

    要克隆Java中的列表,最简单的方法是使用ArrayList.clone()方法- 示例import java.util.ArrayList; public class Demo { public s ...

  5. java对列表数据排序_如何在Java中对列表进行排序

    java对列表数据排序 Sometimes we have to sort a list in Java before processing its elements. In this tutoria ...

  6. java遍历是什么意思_遍历Java String行的最佳方法是什么?

    遍历Java String行的最佳方法是什么? 目前,我正在使用类似: String[]lines = textContent.split(System.getProperty("line. ...

  7. java中的invoke方法_详解Java中Method的Invoke方法

    在写代码的时候,发现从父类class通过getDeclaredMethod获取的Method可以调用子类的对象,而子类改写了这个方法,从子类class通过getDeclaredMethod也能获取到M ...

  8. layui循环遍历数据_layuiAdmin循环遍历展示商品图片列表的方法

    主页面内容 新增 {{# layui.each(d.list, function(index, item){ }} {{# if(item.cover_img == ""){ }} ...

  9. 在java中下列描述错误的是_在 JAVA 中 , 关于类的方法 , 下列描述错误的是 ()._学小易找答案...

    [多选题]价值的特性是 [简答题]输入任一字符串,统计其中数字,字母及其它字符个数 .(25分) [填空题]1.产品整体包括哪五个基本层次 2核心层次产品最基本的层次,是产品的_____ [单选题]纸 ...

最新文章

  1. YML(2)yml 语法
  2. c++ 隐式类型转换
  3. Windows系统进程全解剖
  4. 通过设计国际象棋游戏来了解策略模式
  5. 3d打印光固化好还是热固化好_UV专利一览(71) —天啦噜!3D打印上太空!
  6. 怎样改动SharePoint管理中心的语言
  7. ural(Timus) 1019 Line Painting
  8. Spark SQL运行架构
  9. 11月7日简单标签与Listener培训日记
  10. ECharts3使用入门
  11. Spring boot应用【tailf】服务启动停止管理脚本
  12. ArcGIS 实验理论基础二十二 空间插值
  13. Python实现视频中的音频提取
  14. [链接汇总]在用Matlab解微分方程时比较有用
  15. Joint 3D Proposal Generation and Object Detection from View Aggregation论文学习
  16. Android音视频通话环境搭建
  17. 滕州小学计算机教室,东湖教育四十年|滕州小学--小学校 大世界
  18. vue搜索(不区分大小写)通用
  19. JavaCV音视频开发宝典:JavaCV使用gdigrab方式实现windows录屏(windows屏幕画面抓取/采集,可实现高帧率屏幕截屏、录屏功能)
  20. Greenplum-Spark Connector 介绍

热门文章

  1. swift网络编程入门应用:天气预报
  2. lnmp部署 -----1
  3. Set static ip for ubuntu
  4. PostgreSQl中 index scan 代价的进一步学习
  5. css滤镜使文字变3D效果
  6. 操作系统学习(二)、分段机制
  7. undefined与null
  8. OnTouchListener与OnClickListener冲突问题解决思路
  9. 文本框获取焦点时,去掉边框
  10. livevent的几个问题