为什么通过ArrayList <string>循环与常规数组相同?</string>

时间:2013-07-21 05:20:56

标签: java

方法1

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

for (String s : list) {
    write.append(s);
    write.append('\n');
}

如何以这种方式循环ArrayList?这种方法不适用于静态常规数组,例如:

String[] list2 = new String[]{"1","2","3","4"};

如果我想循环ArrayList<String> list,为什么不这样做,例如:

   方法2

for (int i = 0; i < list.size(); i++) {
    write.append(list.get(i));
    write.append("\n");
}

我只是不明白如何使用方法1 。欢迎任何解释。

5 个答案:

答案 0 :(得分:3)

ArrayList实现了Iterable,这使得它提供了一个Iterator对象,然后用户通过for循环。

任何实现Iterable的类都可以在for循环中使用,就像数组一样。

对于数组和集合,简化的for循环看起来是相同的,但在引擎盖下,它使用数组的索引和集合的迭代器。

答案 1 :(得分:3)

这些被称为 - 每个循环,并且可以应用于数组和集合。格式:

for ([type] [var-name] : [array or iterable value]) {
    ...
}

要使用for-each循环,您只需要满足以下两个条件之一:

  1. 迭代值是一个数组,或
  2. 迭代值为Iterable
  3. 我们这样做的最大原因是List不是我们可以在循环中使用的唯一Iterable,但 是唯一可以使用的HashSet索引即可。这允许您进行通用迭代,而不是将自己锁定为固定的索引列表格式。

    例如,HashSet<String> strs = new HashSet<String>(); for (String str : strs) { ... } 没有排序,但我仍然可以在for-each循环中迭代它:

    Iterable

    我还可以使用List代替public static void printStrings(Iterable<String> strs) { for (String str : strs) { System.out.println(str); } }

    List

    我无法使用索引对其进行迭代,而无需先将其复制到其他内容中,例如数组或Iterator

    使用for-each循环的另一个重要原因是它编译为使用列表中的Iterable.iterator()(通过ConcurrentModificationException),这允许快速失败迭代。这导致像ConcurrentModificationException这样的事情告诉我们在我们迭代它时修改了集合。例如,这将始终抛出List<String> strs = ... ; for (String str : strs) { strs.remove(str); }

    List<String> strs = ... ;
    for (int i = 0; i < strs.length(); i++) {
        strs.remove(str);
    }
    

    但这不会:

    List

    这对多线程应用程序很有用,因为你应该在访问它之前锁定列表,因为大多数Iterator实现不是为了线程安全而设计的,迭代是从不线程安全,没有外部同步,索引都带有ConcurrentModificationException。如果一个线程正在迭代它而另一个线程对其进行更改,则可以(不保证,但可以)抛出{{1}},这会告诉您列表未正确锁定。索引的索引永远不会给你这种信息。相反,它只会表现出像跳过元素这样的奇怪行为。

答案 2 :(得分:2)

有一个名为Iterable的接口允许快速迭代。如果某些东西实现Iterable,则允许快速迭代。 Iterable接口有一个方法,它返回一个Iterator,可用于迭代元素。

答案 3 :(得分:1)

这是for-each语法:http://docs.oracle.com/javase/1.5.0/docs/guide/language/foreach.html

编译器会将方法1中的代码转换为:

for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
  String s = iterator.next();
  write.append(s);
  write.append('\n');
}

答案 4 :(得分:1)

第一个称为enhanced-for,或“为每个”。它被认为是for语句的传统模型的语法糖 - 允许您遍历集合中的每个元素 - 无论是数组还是Java Collections Framework中的任何内容。

这些类型的循环之间存在两个明显的差异:

  • 增强的for语句为您索引值,并将其作为声明的一部分存储在临时变量中。因此,您不必执行val[i]value.get(i)之类的操作 - 这会自动发生。
  • 您无法在增强型for语句中指定增量;您要么迭代集合中的所有元素,要么通过break语句提前终止。

在JLS中定义了可以使用标准数组迭代的原因,特别是§14.14.2 - 因为数组没有实现Iterable,所以它将它转换为标准行为{ {1}}陈述。

  
      
  • ...否则,Expression必须具有数组类型T []。

         

    for成为紧接在增强for语句之前的标签序列(可能为空)。

  •   
     

增强的for语句相当于表单的基本for语句:

L1 ... Lm
     

#a和#i是自动生成的标识符,这些标识符与增强的for语句发生时的范围内的任何其他标识符(自动生成或其他标识符)不同。