遍历列表,更好的方法

Posted

技术标签:

【中文标题】遍历列表,更好的方法【英文标题】:Looping through lists, better method 【发布时间】:2015-05-27 18:23:30 【问题描述】:

当我在 Java 中编码和发现新的做事方式时,我总是对通过列表循环输出数据的更好方法感到困惑。

在下面的示例中,我正在遍历列表并使用一个计数器,所以很多时候我不得不在输出中包含一个索引计数器。

我偏爱方法 1,但我发现这些方法中的任何一种都有些过时了。我见过很多循环遍历列表的例子,主要使用的是方法 2。

所以我的问题是什么是更好的方法,如果所有这些方法都一样,那么最标准的是什么?

private ArrayList<String> list = new ArrayList<String>();

public Test() 
    list.add("One");        
    list.add("Two");        
    list.add("Three");      
    list.add("Four");       
    list.add("Five");

    method1();
    method2();
    method3();


public void method1() 
    System.out.println("Method 1");
    int i = 1;
    for (String value:list) 
        System.out.println((i++) + " = " + value);
    


public void method2() 
    System.out.println("Method 2");
    for (int i = 0; i < list.size(); i++) 
        System.out.println((i+1) + " = " + list.get(i));
    


public void method3() 
    System.out.println("Method 3");
    Iterator<String> it = list.iterator();
    int i = 1;
    while (it.hasNext()) 
        System.out.println((i++) + " = " + it.next());
    

【问题讨论】:

Ways to iterate over a List in java? 的可能重复项 Kenster,感谢您让我知道可能的重复。我的问题更倾向于使用索引输出。但我/我们还发现,在 Java 8 的新版本中,现在有了新的遍历列表的方法。 您想知道哪个更好,但没有提供评估哪个更好的标准。 【参考方案1】:

method3() 使用Iterator 是遍历列表的最佳方式。尽管method1()在幕后使用Iterator,但如果你想在循环内修改列表,比如更新或删除,可能会导致ConcurrentModificationException

【讨论】:

【参考方案2】:

第一个更好,更不容易出错。

public void method1() 
    System.out.println("Method 1");
    int i = 1;
    for (String value:list) 
        System.out.println((i++) + " = " + value);
    

第二个选项与您正在使用的集合紧密耦合。这意味着,如果有人更改了数据结构,那么他/她也必须更改 for 循环的代码。

第三个选项,当你必须使用嵌套循环并且必须处理多个迭代器时,迭代器会变得很丑。

查看以下链接,了解迭代器容易出错的用法。 https://docs.oracle.com/javase/8/docs/technotes/guides/language/foreach.html

【讨论】:

【参考方案3】:

method1() 类似于method3(),因为 for-each 循环在后台使用 List 的迭代器。与method3() 的不同之处在于您实际上可以访问此迭代器,因此如果您希望从列表中删除元素,可以对其调用 remove。

另一方面,method2() 可能会导致“糟糕”的性能,具体取决于底层实现。如果您的列表是LinkedList,则get 具有O(n) 复杂度时间,因此for 循环将具有O(n^2) 复杂度。使用迭代器,您将始终在恒定时间内获得下一个元素。

我个人会使用 1,它编写的代码也更少,如果您的意图是对数据结构执行只读操作,这是 for-each 循环的主要好处之一。

如果您使用的是 Java 8 并且不需要打印索引,您也可以这样做:

list.forEach(System.out::println);

【讨论】:

int index = 1; list.forEach(e-&gt;System.out.println((index++)+" = "+e));你也可以打印索引 @Loki 不,lambda 中的变量必须是有效的最终变量。你可以使用AtomicInteger,虽然它有点矫枉过正。 你是对的。不过我留下评论,所以每个人都可以像我一样学习 根据您关于使用迭代器删除元素的评论,在迭代列表时更改列表不是一件坏事吗?坏事可能会在你的脸上爆炸,但有例外。 @Davor 不是通过迭代器的 remove 方法。文档states “请注意,Iterator.remove 是在迭代期间修改集合的唯一安全方法;如果在迭代过程中以任何其他方式修改基础集合,则行为未指定。”我>【参考方案4】:

没有。使用 lambda 表达式,在 java 8 中可用。

如果使用 Java

【讨论】:

您能否提供更多细节或示例?这是一个低质量的答案

以上是关于遍历列表,更好的方法的主要内容,如果未能解决你的问题,请参考以下文章

遍历非常大的 JSON 数组

nextAll() - 多个列表遍历

通过遍历列表为 pandas 列赋值

Python - 遍历没有最后一个元素的列表

三种遍历列表里面序号和值的方法

Python小技巧:列表推导式替代循环遍历