Kotlin中 for in 是有序的吗?forEach呢?

我们要遍历一个数组、一个列表,经常会用到kotlin的 for in 语法,但是 for in 是不是有序的呢?forEach是不是有序的呢?这就需要看一下它们的本质了。

数组的 for in

kotlin 复制代码
// 调用:
val arr = arrayOf(1, 2, 3)
for (ele in arr) {
    println(ele)
}

反编译成Java是个什么东西呢?

java 复制代码
Integer[] arr = new Integer[]{1, 2, 3};
Integer[] var4 = arr;
int var5 = arr.length;

for(int var3 = 0; var3 < var5; ++var3) {
    int ele = var4[var3];
    System.out.println(ele);
}

总结:从Java代码可以看出,实际就是一个普通的for循环,是从下标0开始遍历到结束的,所以是有序的。

列表的 for in

kotlin 复制代码
// 调用:
val list = listOf(1, 2, 3)
for (ele in list) {
    println(ele)
}

反编译成Java:

java 复制代码
List list = CollectionsKt.listOf(new Integer[]{1, 2, 3});
Iterator var3 = list.iterator();

while(var3.hasNext()) {
    int ele = ((Number)var3.next()).intValue();
    System.out.println(ele);
}

可以看出列表的for in是通过iterator实现的,和数组不一样,那这个iterator遍历是否是有序的呢?首先我们要知道这个iterator怎么来的:

kotlin 复制代码
// iterator 是通过调用 list.iterator() 得到的,那么这个list又是什么呢?
Iterator var3 = list.iterator();

// list
List list = CollectionsKt.listOf(new Integer[]{1, 2, 3});

// list是通过数组elements.asList()得到的
public fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()

// 这里有个expect,找到对应的actual
public expect fun <T> Array<out T>.asList(): List<T>

// 对应的actual
public actual fun <T> Array<out T>.asList(): List<T> {
    return ArraysUtilJVM.asList(this)
}

// 最终调用了Arrays.asList(array)
class ArraysUtilJVM {
    static <T> List<T> asList(T[] array) {
        return Arrays.asList(array);
    }
}

public class Arrays {
    
    // 从这里看到最终拿到的list是 Arrays 类中的 ArrayList
    // 然后我们找到里面的 iterator() 方法
    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;

        @Override
        public Iterator<E> iterator() {
            // 最终得到的iterator是ArrayItr
            // 这里的a是一个数组,也就是我们一开始传进来的1,2,3
            return new ArrayItr<>(a);
        }
    }

    private static class ArrayItr<E> implements Iterator<E> {
        private int cursor;
        private final E[] a;

        ArrayItr(E[] a) {
            this.a = a;
        }

        @Override
        public boolean hasNext() {
            return cursor < a.length;
        }

        @Override
        public E next() {
            int i = cursor;
            if (i >= a.length) {
                throw new NoSuchElementException();
            }
            cursor = i + 1;
            return a[i];
        }
    }
}

总结:列表的for in是通过iterator实现的,这个iterator是ArrayItr,从里面的next()方法可以看出,这也是有序的,从cursor开始,cursor默认是0,也就是从下标0开始遍历。 注:这里只是分析了Arrays.ArrayList的iterator,具体的集合类需要具体分析,比如ArrayList、LinkedList等,不过从正常思维来看,iterator是一个迭代器,就应该有序的把数据一个一个丢出来。

数组的 forEach

kotlin 复制代码
// 调用:
val arr = arrayOf(1, 2, 3)
arr.forEach {
    println(it)
}

// 点进去forEach看:
// 其实也是调用了for in,所以也是有序的。
public inline fun <T> Array<out T>.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}

列表的 forEach

kotlin 复制代码
// 调用:
val list = listOf(1, 2, 3)
list.forEach {
    println(it)
}

// 点进去forEach看:
// 其实也是调用了for in,所以也是有序的。
public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    for (element in this) action(element)
}
相关推荐
赏金术士2 小时前
Android 动画对比指南:View 系统 vs Jetpack Compose
android·kotlin·compose
plainGeekDev3 小时前
Kotlin核心:空安全都搞不明白,还敢说熟练Kotlin?
android·面试·kotlin
jzlhll1235 小时前
Kotlin 协程高级用法之 NonCancellable
android·开发语言·kotlin
JohnnyDeng946 小时前
Paging 3 分页加载架构全解析:从数据源到 UI 的完整链路
android·ui·kotlin
高林雨露7 小时前
kotlin 相关code
开发语言·kotlin
huaCodeA8 小时前
Android面试-Kotlin作用域函数
android·面试·kotlin
QING6181 天前
Kotlin inline 实战详解 —— 新手须知
android·kotlin·android jetpack
Ehtan_Zheng1 天前
Kotlin Flow:combine()、merge() 和 zip() 的区别 —— 不要再互相替代使用
kotlin
高林雨露1 天前
Java 转 Kotlin 对照开发指南
java·开发语言·kotlin
o丁二黄o1 天前
语义版本控制:用Gemini镜像站实现合同条款的深度差异分析与风险追踪
javascript·kotlin·scala