以下是代码片段:
int[] arr = {1, 2, 3};
for (int i : arr)
System.out.println(i);
我有以下问题:
- 上述for-each循环如何工作?
- 如何在Java中获取数组的迭代器?
- 数组是否转换为列表以获取迭代器?
以下是代码片段:
int[] arr = {1, 2, 3};
for (int i : arr)
System.out.println(i);
我有以下问题:
Iterator
,可以使用其中一种直接实现,而不是将数组包装在List
中。例如:
Apache Commons Collections ArrayIterator
com.Ostermiller.util.ArrayIterator
Iterator
,则无法实现,因为基本类型不能是泛型参数。例如,如果您想要一个Iterator<int>
,则必须使用Iterator<Integer>
,如果它是由int[]
支持的,那么会导致大量的自动装箱和拆箱。ArrayIt
显示任何建议;假设所有第三方库。 - Mark JeronimusIterator
(除非当然先将其转换为List
)。Arrays.asList(arr).iterator();
或编写自己的代码,实现ListIterator接口。
Arrays.asList()
方法不能接受一个 int[]
,只能接受 Object[]
及其子类作为参数。 - ILMTitanList<int[]>
,因此是一个Iterator<int[]>
,而不是一个List<Integer>
! - njzk2Arrays.asList()
使用实际数组并将其包装在一个适配器类中,以使其适应列表接口。因此,除了“不支持基元类型”问题(以及对于在非基元情况下遇到相同问题的人)外,这实际上是一个很好的解决方案。 - JasperGoogle的Guava Libraries集合提供了如下功能:
Iterator<String> it = Iterators.forArray(array);
相比于已经似乎被放弃的Apache Collection,应该更喜欢使用Guava。
int[]
)时,这不再适用:(因为我们无法指定Iterator<int>
或Iterator<Integer>
。 - chakrit在Java 8中:
Arrays.stream(arr).iterator();
public class ArrayIterator<T> implements Iterator<T> {
private T array[];
private int pos = 0;
public ArrayIterator(T anArray[]) {
array = anArray;
}
public boolean hasNext() {
return pos < array.length;
}
public T next() throws NoSuchElementException {
if (hasNext())
return array[pos++];
else
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
Iterator<Integer> it = Arrays.asList(arr).iterator();
上面的答案是错误的,你不能在原始数组上使用 Arrays.asList()
,它会返回一个 List<int[]>
。而应该使用 Guava 的 Ints.asList()
。您无法直接获取数组的迭代器。
但是,您可以使用一个由您的数组支持的List,并在此列表上获取迭代器。为此,您的数组必须是Integer数组(而不是int数组):
Integer[] arr={1,2,3};
List<Integer> arrAsList = Arrays.asList(arr);
Iterator<Integer> iter = arrAsList.iterator();
Arrays.asList
会隐式地将数组中的值进行装箱处理,从而确保结果真正是一个List<Integer>
。 - Konrad Rudolph和许多其他数组特性一样,JSL明确提到了数组并赋予它们神奇的属性。JLS 7 14.14.2:
EnhancedForStatement:
for ( FormalParameter : Expression ) Statement
Iterable
的子类型,则翻译如下:T[]
。[[ MAGIC! ]]L1 ... Lm
是增强型for循环语句之前(可能为空的)标签的序列。T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
VariableModifiersopt TargetType Identifier = #a[#i];
Statement
}
#a
和#i
是自动生成的标识符,与任何其他在加强型for语句出现点的作用域中的标识符(自动生成的或其他)都不同。
让我们使用javap
进行分析:
public class ArrayForLoop {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
for (int i : arr)
System.out.println(i);
}
}
那么:
javac ArrayForLoop.java
javap -v ArrayForLoop
main
方法进行了一些编辑,使其更易于阅读:
0: iconst_3
1: newarray int
3: dup
4: iconst_0
5: iconst_1
6: iastore
7: dup
8: iconst_1
9: iconst_2
10: iastore
11: dup
12: iconst_2
13: iconst_3
14: iastore
15: astore_1
16: aload_1
17: astore_2
18: aload_2
19: arraylength
20: istore_3
21: iconst_0
22: istore 4
24: iload 4
26: iload_3
27: if_icmpge 50
30: aload_2
31: iload 4
33: iaload
34: istore 5
36: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
39: iload 5
41: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
44: iinc 4, 1
47: goto 24
50: return
分解:
0
到 14
: 创建数组15
到 22
: 准备 for 循环。在 22 处,从堆栈中将整数 0
存储到本地位置 4
。那就是循环变量。24
到 47
: 循环。循环变量在 31
处被检索,并在 44
处递增。当它等于存储在本地变量 3 中的数组长度,该数组长度在 27
处进行检查时,循环结束。结论: 它与使用索引变量显式执行 for 循环相同,不涉及迭代器。
对于(2),Guava提供了恰好符合您要求的内容,即Int.asList()。 相应类中的每种原语类型都有一个相应的等效类,例如Booleans
代表boolean
等。
int[] arr={1,2,3};
for(Integer i : Ints.asList(arr)) {
System.out.println(i);
}