Java 增强的 for 语句如何对数组起作用,以及如何获取数组的迭代器?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3912765/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does the enhanced for statement work for arrays, and how to get an iterator for an array?
提问by Emil
Given the following code snippet:
鉴于以下代码片段:
int[] arr = {1, 2, 3};
for (int i : arr)
System.out.println(i);
I have the following questions:
我有以下问题:
- How does the above for-each loop work?
- How do I get an iterator for an array in Java?
- Is the array converted to a list to get the iterator?
- 上面的 for-each 循环是如何工作的?
- 如何在 Java 中获取数组的迭代器?
- 是否将数组转换为列表以获取迭代器?
采纳答案by uckelman
If you want an Iterator
over an array, you could use one of the direct implementations out there instead of wrapping the array in a List
. For example:
如果你想要一个Iterator
数组,你可以使用直接实现之一,而不是将数组包装在List
. 例如:
Apache Commons Collections ArrayIterator
Apache Commons 集合 ArrayIterator
Or, this one, if you'd like to use generics:
或者,这个,如果你想使用泛型:
com.Ostermiller.util.ArrayIterator
com.Ostermiller.util.ArrayIterator
Note that if you want to have an Iterator
over primitive types, you can't, because a primitive type can't be a generic parameter. E.g., if you want an Iterator<int>
, you have to use an Iterator<Integer>
instead, which will result in a lot of autoboxing and -unboxing if that's backed by an int[]
.
请注意,如果您想拥有Iterator
over 原始类型,则不能,因为原始类型不能是泛型参数。例如,如果你想要一个Iterator<int>
,你必须使用 anIterator<Integer>
来代替,如果有一个int[]
.
回答by Péter T?r?k
No, there is no conversion. The JVM just iterates over the array using an index in the background.
不,没有转换。JVM 只是在后台使用索引迭代数组。
Quote from Effective Java 2nd Ed., Item 46:
引自 Effective Java 第二版,第 46 项:
Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once.
请注意,使用 for-each 循环没有性能损失,即使是数组也是如此。事实上,在某些情况下,它可能比普通的 for 循环提供轻微的性能优势,因为它只计算一次数组索引的限制。
So you can't get an Iterator
for an array (unless of course by converting it to a List
first).
所以你不能得到一个Iterator
数组(当然除非将它转换为List
第一个)。
回答by Jochem
Arrays.asList(arr).iterator();
Arrays.asList(arr).iterator();
Or write your own, implementing ListIterator interface..
或者自己编写,实现 ListIterator 接口..
回答by Benoit Courtine
You can't directly get an iterator for an array.
您不能直接获取数组的迭代器。
But you can use a List, backed by your array, and get an ierator on this list. For that, your array must be an Integerarray (instead of an int array):
但是你可以使用一个由你的数组支持的 List,并在这个列表上获得一个迭代器。为此,您的数组必须是Integer数组(而不是 int 数组):
Integer[] arr={1,2,3};
List<Integer> arrAsList = Arrays.asList(arr);
Iterator<Integer> iter = arrAsList.iterator();
Note: it is only theory. You can get an iterator like this, but I discourage you to do so. Performances are not good compared to a direct iteration on the array with the "extended for syntax".
注意:这只是理论。您可以获得这样的迭代器,但我不鼓励您这样做。与使用“扩展语法”的数组直接迭代相比,性能并不好。
Note 2: a list construct with this method doesn't support all methods (since the list is backed by the array which have a fixed size). For example, "remove" method of your iterator will result in an exception.
注意 2:具有此方法的列表构造不支持所有方法(因为列表由具有固定大小的数组支持)。例如,迭代器的“remove”方法将导致异常。
回答by Sean Patrick Floyd
Strictly speaking, you can't get an iterator of the primitive array, because Iterator.next()can only return an Object. But through the magic of autoboxing, you can get the iterator using the Arrays.asList()method.
严格来说,不能得到原始数组的迭代器,因为Iterator.next()只能返回一个Object。但是通过自动装箱的魔力,您可以使用Arrays.asList()方法获取迭代器。
Iterator<Integer> it = Arrays.asList(arr).iterator();
Iterator<Integer> it = Arrays.asList(arr).iterator();
The above answer is wrong, you can't use Arrays.asList()
on a primitive array, it would return a List<int[]>
. Use Guava's Ints.asList()
instead.
上面的答案是错误的,你不能Arrays.asList()
在原始数组上使用,它会返回一个List<int[]>
. 利用番石榴的Ints.asList()
来代替。
回答by 30thh
Google Guava Libraries collection provides such function:
Google Guava Libraries collection 提供了这样的功能:
Iterator<String> it = Iterators.forArray(array);
One should prefere Guava over the Apache Collection (which seems to be abandoned).
人们应该更喜欢 Guava 而不是 Apache Collection(它似乎被放弃了)。
回答by Robert Carnegie
I'm a recent student but I BELIEVE the original example with int[] is iterating over the primitives array, but not by using an Iterator object. It merely has the same (similar) syntax with different contents,
我是最近的学生,但我相信 int[] 的原始示例正在迭代基元数组,但不是通过使用 Iterator 对象。它只是具有相同(相似)的语法和不同的内容,
for (primitive_type : array) { }
for (object_type : iterableObject) { }
Arrays.asList() APPARENTLY just applies List methods to an object array that it's given - but for any other kind of object, including a primitive array, iterator().next() APPARENTLY just hands you the reference to the original object, treating it as a list with one element. Can we see source code for this? Wouldn't you prefer an exception? Never mind. I guess (that's GUESS) that it's like (or it IS) a singleton Collection. So here asList() is irrelevant to the case with a primitives array, but confusing. I don't KNOW I'm right, but I wrote a program that says that I am.
Arrays.asList() 似乎只是将 List 方法应用于它给定的对象数组 - 但对于任何其他类型的对象,包括原始数组, iterator().next() 似乎只是将引用传递给原始对象,处理它是一个包含一个元素的列表。我们可以看到这个的源代码吗?你不喜欢例外吗?没关系。我猜(那是 GUESS)它就像(或者它是)一个单例集合。所以这里 asList() 与原始数组的情况无关,但令人困惑。我不知道我是对的,但我写了一个程序,说我是对的。
Thus this example (where basically asList() doesn't do what you thought it would, and therefore is not something that you'd actually use this way) - I hope the code works better than my marking-as-code, and, hey, look at that last line:
因此,这个例子(基本上 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());
}
}
回答by Ashok Domadiya
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();
}
}
回答by BeeOnRope
For (2), Guava provides exactly what you want as Int.asList(). There is an equivalent for each primitive type in the associated class, e.g., Booleans
for boolean
, etc.
对于(2),Guava 提供了你想要的Int.asList()。关联类中的每个原始类型都有一个等效项,例如Booleans
forboolean
等。
int[] arr={1,2,3};
for(Integer i : Ints.asList(arr)) {
System.out.println(i);
}
回答by Max Hohenegger
I like the answer from 30thh using Iterators
from Guava. However, from some frameworks I get null instead of an empty array, and Iterators.forArray(array)
does not handle that well. So I came up with this helper method, which you can call with Iterator<String> it = emptyIfNull(array);
我喜欢Iterators
来自 Guava 的30thh 的答案。但是,在某些框架中,我得到的是 null 而不是空数组,并且Iterators.forArray(array)
处理得不好。所以我想出了这个辅助方法,你可以用它来调用Iterator<String> it = emptyIfNull(array);
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;
}
};
}