在Java中迭代列表的方法?

  • 回答 (2)
  • 关注 (0)
  • 查看 (77)

对于Java语言来说,我尝试熟悉所有的方法,以便可以遍历列表以及每个方法的优缺点。

给定一个List<E> list对象,我知道以下方法遍历所有元素:

基本的 循环(当然,也有相同的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
    // ...
}

注意:这个形式对于迭代Lists来说是一个糟糕的选择,因为这个get方法的实际实现可能不如使用一个方法的效率Iterator。例如,LinkedList实现必须遍历i之前的所有元素才能获得第i个元素。在上面的例子中,List实现没有办法“保存它的位置”,以使未来的迭代更有效率。对于一个ArrayList它并不重要,因为复杂性/成本get是恒定的时间(O(1)),而对于一个LinkedList是成正比的列表(O(n))的大小。

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

编辑:添加ListIterato

的ListIterato

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

编辑:添加从Java 8的Stream API的地图方法

Iterable.forEach,Stream.forEach,...

在实现的Java 8集合类Iterable(例如所有Lists)中,现在有一个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 greate
// utilization of parallelism
// (caution: consequently, order of execution is not guaranteed,
// see [Stream.forEachOrdered][stream-foreach-ordered] for more
// information about this.)

还有什么其他的方式,如果有的话?

火星救援队长火星救援队长提问于
最爱开车啦互联网的敏感者回答于

问题中列出的每种类型的示例:

ListIterationExample.java
import java.util.*;
public class ListIterationExample {
     public static void main(String []args){
        List<Integer> numbers = new ArrayList<Integer>();
        // populates list with initial values
        for (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 value
        for (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 changed
        for (Integer number : numbers) {
            number++; // number = new Integer(number+1);
        }
        printList(numbers);         // 0,2,4,6,8,10,12,14  
        // same as above -- just different syntax
        for (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 curso
        for (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 curso
        for (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 elements
        for (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 comma
        System.out.println(sb.toString());
     }
}
心愿回答于

循环的三种形式几乎相同。增强的for循环:

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

根据Java语言规范,与传统for循环迭代器的明确使用相同。在第三种情况下,只能通过删除当前元素来修改列表内容,并且只能通过remove迭代器本身的方法来完成。使用基于索引的迭代,您可以自由地以任何方式修改列表。但是,添加或删除当前索引之前的元素可能会导致循环跳过元素或处理相同的元素多次; 您需要在进行此类更改时正确调整循环索引。

在所有情况下,element都是对实际列表元素的引用。迭代方法都不会在列表中生成任何副本。element列表中相应元素的内部状态将始终显示内部状态的更改。

从本质上讲,只有两种方法可以遍历列表:使用索引或使用迭代器。增强的for循环只是Java 5中引入的一种语法快捷方式,可以避免显式定义迭代器的麻烦。对于这两种款式,你可以拿出本质琐碎的变化使用for,while或do while块,但他们都归结为同样的事情(或者说,两件事情)。

编辑:你可以使用a ListIterator来迭代您设置列表的当前元素。您将需要使用List#listIterator()而不是List#iterator()初始化循环变量(显然,必须被声明为一个ListIterator而不是一个Iterator)。

扫码关注云+社区

领取腾讯云代金券