Java 增强的for语句如何用于数组,以及如何获取数组的迭代器?
给定以下代码段:Java 增强的for语句如何用于数组,以及如何获取数组的迭代器?,java,arrays,iterator,foreach,Java,Arrays,Iterator,Foreach,给定以下代码段: int[] arr = {1, 2, 3}; for (int i : arr) System.out.println(i); 我有以下问题: 上述每个循环是如何工作的 如何在Java中获得数组的迭代器 数组是否转换为列表以获取迭代器 不,没有转换。JVM只是在后台使用索引遍历数组 有效Java第二版第46项的报价: 请注意,使用此选项不会导致性能损失 对于每个循环,甚至对于阵列,都会使用。事实上,它可能会提供一点性能优势 在某些情况下,在普通for循环上,因为它计算
int[] arr = {1, 2, 3};
for (int i : arr)
System.out.println(i);
我有以下问题:
不,没有转换。JVM只是在后台使用索引遍历数组 有效Java第二版第46项的报价: 请注意,使用此选项不会导致性能损失 对于每个循环,甚至对于阵列,都会使用。事实上,它可能会提供一点性能优势 在某些情况下,在普通for循环上,因为它计算 数组索引只有一次 因此,无法为数组获取
迭代器(当然,除非首先将其转换为列表)
或者编写自己的,实现ListIterator接口。您不能直接为数组获取迭代器
但您可以使用数组支持的列表,并在该列表上获取一个ierator。为此,数组必须是整数数组(而不是int数组):
Integer[]arr={1,2,3};
List arrAsList=Arrays.asList(arr);
迭代器iter=arrAsList.Iterator();
注:这只是理论。您可以得到这样的迭代器,但我不鼓励您这样做。与使用“extended for syntax”在数组上直接迭代相比,性能并不好
注2:使用此方法的列表构造不支持所有方法(因为列表由具有固定大小的数组支持)。例如,迭代器的“remove”方法将导致异常。严格来说,您无法获得基元数组的迭代器,因为它只能返回一个对象。但是通过自动装箱的魔力,您可以使用该方法获得迭代器
Iterator it=Arrays.asList(arr.Iterator();
上面的答案是错误的,您不能在基元数组上使用数组。asList()
,它将返回一个列表
。改为使用的Ints.asList()
。如果希望在数组上使用迭代器,可以使用其中一个直接实现,而不是将数组包装在列表中。例如:
int[] arr = {1, 2, 3};
Iterator<Integer> iterator = Arrays.stream(arr).mapToObj(Integer::valueOf).iterator();
或者,这个,如果你想使用泛型:
请注意,如果您想在基本类型上拥有一个迭代器,则不能,因为基本类型不能是泛型参数。例如,如果你想要一个迭代器
,你必须使用迭代器
,这将导致大量的自动装箱和-取消装箱,如果这是由int[]
谷歌的集合提供的功能支持的话:
Iterator<String> it = Iterators.forArray(array);
Iterator it=Iterators.forArray(数组);
人们应该更喜欢Guava而不是Apache集合(它似乎已经被放弃了)。我是一名新学生,但我相信int[]的原始示例是迭代原语数组,而不是使用迭代器对象。它只是有相同(相似)的语法和不同的内容
for (primitive_type : array) { }
for (object_type : iterableObject) { }
Arrays.asList()显然只是将列表方法应用于给定的对象数组,但对于任何其他类型的对象,包括基元数组,iterator()。next()显然只是将原始对象的引用交给您,将其视为一个包含一个元素的列表。我们能看看这个的源代码吗?你不喜欢例外吗?不要介意。我猜(那是猜测)它就像(或它是)一个单身的集合。因此,这里的asList()与基元数组的情况无关,但令人困惑。我不知道我是对的,但我写了一个程序说我是对的
因此,在这个示例中(基本上asList()并没有做您认为会做的事情,因此您实际上不会使用这种方式)-我希望代码比标记为代码更好,并且,嘿,看看最后一行:
// Java(TM) SE Runtime Environment (build 1.6.0_19-b04)
import java.util.*;
public class Page0434Ex00Ver07 {
public static void main(String[] args) {
int[] ii = new int[4];
ii[0] = 2;
ii[1] = 3;
ii[2] = 5;
ii[3] = 7;
Arrays.asList(ii);
Iterator ai = Arrays.asList(ii).iterator();
int[] i2 = (int[]) ai.next();
for (int i : i2) {
System.out.println(i);
}
System.out.println(Arrays.asList(12345678).iterator().next());
}
}
公共类ArrayIterator实现迭代器{
专用T数组[];
私人int pos=0;
公共阵列计数器(T anArray[]{
数组=数组;
}
公共布尔hasNext(){
返回位置<数组长度;
}
public T next()抛出NoTouchElementException{
if(hasNext())
返回数组[pos++];
其他的
抛出新的NoTouchElementException();
}
公共空间删除(){
抛出新的UnsupportedOperationException();
}
}
对于第(2)项,番石榴提供的正是您想要的。关联类中的每个基元类型都有一个等价项,例如,Booleans
对应于boolean
,等等
int[] arr={1,2,3};
for(Integer i : Ints.asList(arr)) {
System.out.println(i);
}
我喜欢用番石榴的迭代器从第30天得到的答案。然而,在一些框架中,我得到的是null而不是空数组,并且迭代器。所以我提出了这个helper方法,您可以使用Iterator it=emptyIfNull(array)调用它代码>
public静态不可修改迭代器emptyIfNull(F[]数组){
if(数组!=null){
返回迭代器.forArray(数组);
}
返回新的不可修改迭代器(){
公共布尔hasNext(){
返回false;
}
公共基金下一期(){
返回null;
}
};
}
在Java 8中:
Arrays.stream(arr).iterator();
上述每个循环是如何工作的?
与许多其他数组功能一样,JSL明确提到数组并赋予它们神奇的属性:
[……]
如果表达式类型是Iterable
的子类型,则翻译如下
[……]
否则,表达式必须具有数组类型,T[]
。[[魔法!]]
让L1。。。Lm
是紧靠增强型for语句前面的标签序列(可能为空)
增强型for语句相当于以下形式的基本for语句:
然后:
main
me
int[] arr={1,2,3};
for(Integer i : Ints.asList(arr)) {
System.out.println(i);
}
public static <F> UnmodifiableIterator<F> emptyIfNull(F[] array) {
if (array != null) {
return Iterators.forArray(array);
}
return new UnmodifiableIterator<F>() {
public boolean hasNext() {
return false;
}
public F next() {
return null;
}
};
}
Arrays.stream(arr).iterator();
EnhancedForStatement:
for ( FormalParameter : Expression ) Statement
T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
VariableModifiersopt TargetType Identifier = #a[#i];
Statement
}
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
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
int[] arr = {1, 2, 3};
for (int n : arr) {
System.out.println(n);
}
int[] arr = {1, 2, 3};
{ // These extra braces are to limit scope; they do not affect the bytecode
int[] iter = arr;
int length = iter.length;
for (int i = 0; i < length; i++) {
int n = iter[i];
System.out.println(n);
}
}
public class Arrays {
public static <T> List<T> asList(T... a) {
return new ArrayList<>(a);
}
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable {
private final E[] a;
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
@Override
public int size() {
return a.length;
}
@Override
public E get(int index) {
return a[index];
}
@Override
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element;
return oldValue;
}
}
}
int[] arr = {1, 2, 3};
Iterator<Integer> iterator = Arrays.stream(arr).mapToObj(Integer::valueOf).iterator();
int[] arr = {1, 2, 3};
IntStream stream = Arrays.stream(arr);
stream.forEach(System.out::println);
int[] arr = {1, 2, 3};
PrimitiveIterator.OfInt iterator = Arrays.stream(arr);
// You can use it as an Iterator<Integer> without casting:
Iterator<Integer> example = iterator;
// You can obtain primitives while iterating without ever boxing/unboxing:
while (iterator.hasNext()) {
// Would result in boxing + unboxing:
//int n = iterator.next();
// No boxing/unboxing:
int n = iterator.nextInt();
System.out.println(n);
}
final int[] arr = {1, 2, 3};
Iterator<Integer> iterator = new Iterator<Integer>() {
int i = 0;
@Override
public boolean hasNext() {
return i < arr.length;
}
@Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return arr[i++];
}
};
public final class IntIterator implements Iterator<Integer> {
private final int[] arr;
private int i = 0;
public IntIterator(int[] arr) {
this.arr = arr;
}
@Override
public boolean hasNext() {
return i < arr.length;
}
@Override
public Integer next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return arr[i++];
}
}