美文网首页
Kotlin中 for in 是有序的吗?forEach呢?

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

作者: 望北8261 | 来源:发表于2023-11-22 22:02 被阅读0次

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

    数组的 for in

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

    反编译成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

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

    反编译成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怎么来的:

    // 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

    // 调用:
    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

    // 调用:
    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)
    }
    

    相关文章

      网友评论

          本文标题:Kotlin中 for in 是有序的吗?forEach呢?

          本文链接:https://www.haomeiwen.com/subject/ijywwdtx.html