方法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 。欢迎任何解释。
答案 0 :(得分:3)
ArrayList
实现了Iterable
,这使得它提供了一个Iterator
对象,然后用户通过for循环。
任何实现Iterable
的类都可以在for循环中使用,就像数组一样。
对于数组和集合,简化的for循环看起来是相同的,但在引擎盖下,它使用数组的索引和集合的迭代器。
答案 1 :(得分:3)
这些被称为 - 每个循环,并且可以应用于数组和集合。格式:
for ([type] [var-name] : [array or iterable value]) {
...
}
要使用for-each循环,您只需要满足以下两个条件之一:
Iterable
。我们这样做的最大原因是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中的任何内容。
这些类型的循环之间存在两个明显的差异:
val[i]
或value.get(i)
之类的操作 - 这会自动发生。break
语句提前终止。在JLS中定义了可以使用标准数组迭代的原因,特别是§14.14.2 - 因为数组没有实现Iterable
,所以它将它转换为标准行为{ {1}}陈述。
...否则,Expression必须具有数组类型T []。
让
for
成为紧接在增强for语句之前的标签序列(可能为空)。增强的for语句相当于表单的基本for语句:
L1 ... Lm
#a和#i是自动生成的标识符,这些标识符与增强的for语句发生时的范围内的任何其他标识符(自动生成或其他标识符)不同。