No, there is no conversion. The JVM just iterates over the array using an index in the background.
Quote from Effective Java 2nd Ed., Item 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.
So you can't get an Iterator for an array (unless of course by converting it to a List first).
But you can use a List, backed by your array, and get an ierator on this list. For that, your array must be an Integer array (instead of an int array):
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.
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<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.
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[].
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,
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.
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:
// 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());
}
}
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();
}
}
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.
int[] arr={1,2,3};
for(Integer i : Ints.asList(arr)) {
System.out.println(i);
}
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);
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;
}
};
}
#a and #i are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where the enhanced for statement occurs.
Is the array converted to a list to get the iterator?
Let's javap it up:
public class ArrayForLoop {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
for (int i : arr)
System.out.println(i);
}
}
then:
javac ArrayForLoop.java
javap -v ArrayForLoop
main method with a bit of editing to make it easier to read:
15 to 22: prepare for the for loop. At 22, store integer 0 from stack into local position 4. THAT is the loop variable.
24 to 47: the loop. The loop variable is retrieved at 31, and incremented at 44. When it equals the array length which is stored in local variable 3 on the check at 27, the loop ends.
Conclusion: it is the same as doing an explicit for loop with an index variable, no itereators involved.
I'm a bit late to the game, but I noticed some key points that were left out, particularly regarding Java 8 and the efficiency of Arrays.asList.
1. How does the for-each loop work?
As Ciro Santilli 六四事件 法轮功 包卓轩 pointed out, there's a handy utility for examining bytecode that ships with the JDK: javap. Using that, we can determine that the following two code snippets produce identical bytecode as of Java 8u74:
For-each loop:
int[] arr = {1, 2, 3};
for (int n : arr) {
System.out.println(n);
}
For loop:
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);
}
}
2. How do I get an iterator for an array in Java?
While this doesn't work for primitives, it should be noted that converting an array to a List with Arrays.asList does not impact performance in any significant way. The impact on both memory and performance is nearly immeasurable.
Arrays.asList does not use a normal List implementation that is readily accessible as a class. It uses java.util.Arrays.ArrayList, which is not the same as java.util.ArrayList. It is a very thin wrapper around an array and cannot be resized. Looking at the source code for java.util.Arrays.ArrayList, we can see that it's designed to be functionally equivalent to an array. There is almost no overhead. Note that I have omitted all but the most relevant code and added my own comments.
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;
}
}
}
The iterator is at java.util.AbstractList.Itr. As far as iterators go, it's very simple; it just calls get() until size() is reached, much like a manual for loop would do. It's the simplest and usually most efficient implementation of an Iterator for an array.
Again, Arrays.asList does not create a java.util.ArrayList. It's much more lightweight and suitable for obtaining an iterator with negligible overhead.
Primitive arrays
As others have noted, Arrays.asList can't be used on primitive arrays. Java 8 introduces several new technologies for dealing with collections of data, several of which could be used to extract simple and relatively efficient iterators from arrays. Note that if you use generics, you're always going to have the boxing-unboxing problem: you'll need to convert from int to Integer and then back to int. While boxing/unboxing is usually negligible, it does have an O(1) performance impact in this case and could lead to problems with very large arrays or on computers with very limited resources (i.e., SoC).
My personal favorite for any sort of array casting/boxing operation in Java 8 is the new stream API. For example:
The streams API also offers constructs for avoiding the boxing issue in the first place, but this requires abandoning iterators in favor of streams. There are dedicated stream types for int, long, and double (IntStream, LongStream, and DoubleStream, respectively).
Interestingly, Java 8 also adds java.util.PrimitiveIterator. This provides the best of both worlds: compatibility with Iterator<T> via boxing along with methods to avoid boxing. PrimitiveIterator has three built-in interfaces that extend it: OfInt, OfLong, and OfDouble. All three will box if next() is called but can also return primitives via methods such as nextInt(). Newer code designed for Java 8 should avoid using next() unless boxing is absolutely necessary.
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);
}
If you're not yet on Java 8, sadly your simplest option is a lot less concise and is almost certainly going to involve boxing:
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++];
}
};
Or if you want to create something more reusable:
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++];
}
}
You could get around the boxing issue here by adding your own methods for obtaining primitives, but it would only work with your own internal code.
3. Is the array converted to a list to get the iterator?
No, it is not. However, that doesn't mean wrapping it in a list is going to give you worse performance, provided you use something lightweight such as Arrays.asList.