I have a very basic forEach
code like the below code.
val array = arrayOf(1, 2)
val list = listOf(1, 2)
array.forEach(::println)
list.forEach(::println)
However, if you decompile it in Java, the implementation method of forEach
differs depending on Array and List.
Integer[] array = new Integer[]{ 1, 2 };
List list = CollectionsKt.listOf(new Integer[]{ 1, 2 });
Integer[] var4 = array;
int var5 = array.length;
int p1;
for(p1 = 0; p1 < var5; p1) {
Object element $iv = var4[p1];
int p1 =((Number) element $iv).intValue();
System.out.println(p1);
}
Iterable $this$forEach$iv = (Iterable)list;
Iterator var11 = $this$forEach$iv.iterator();
while(var11.hasNext()) {
Object element $iv = var11.next();
p1 = ((Number) element $iv).intValue();
System.out.println(p1);
}
As a result of checking the implementation method of forEach
, both were implemented in the same for (element in this) action(element)
method.
public inline fun <T> Array<out T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
for (element in this) action(element)
}
I've been searching for the difference between Array and List to find out why Array and List implementation differently in in
, but I haven't found anything related to the in
keyword. Why does the implementation of in look different for Array and List?
CodePudding user response:
You expected that the code translated to something like:
for (Integer element: array) {
System.out.println(element);
}
for (Integer element: list) {
System.out.println(element);
}
Right? However, note that these for loops in Java are syntactic sugar. These loops are exactly the same as (and this is what the Java compiler will translate those loops to):
Integer[] a = array;
for (int i = 0; i < a.length; i ) {
Integer element = a[i];
System.out.println(element);
}
for (Iterator<Integer> iter = list.iterator(); iterator.hasNext(); ) {
Integer element = (Integer) iterator.next();
System.out.println(element);
}
Noticed how even in Java, arrays and iterables are translated differently. This is specified in the Java Language Specification Section 14.14.2. The reason for this is because arrays do not have an iterator
method in Java (so cannot use the second form), and Iterable
s can't be indexed with []
(so cannot use the first form).
The other differences that you see are mostly due to type erasure, which is why you see casts inserted everywhere, and the implementation details of the decompiler you used. Notice that the second for loop for the list can also be written as the while loop that you see
Iterator<Integer> iter = list.iterator();
while (iterator.hasNext()) {
Integer element = (Integer) iterator.next();
System.out.println(element);
}
Since your decompiler only has the byte code to look at, the question of whether this loop was actually a for loop or a while loop is rather moot.