其类图结构如下:

    其中,Iterator是所有容器类Collection的迭代器。迭代器(Iterator)模式,又叫做游标(Cursor)模式。GOF给出的定义为:提供一种方法访问一个容器对象中各个元素,而又不需暴露该对象的内部细节。 从定义可见,迭代器模式是为容器而生。

    我们可以使用listOf函数来构建一个不可变的List(read-only,只读的List)。它定义在libraries/stdlib/src/kotlin/collections/Collections.kt 里面。关于listOf这个构建函数有下面3个重载函数:

    这些函数创建的List都是是只读的(readonly,也就是不可变的immutable )、可序列化的。

    其中,

    • listOf()用于创建没有元素的空List
    • listOf(vararg elements: T)用于创建只有一个元素的List
    • listOf(element: T)用于创建拥有多个元素的List

    我们使用代码示例分别来演示其用法:

    首先,我们使用listOf()来构建一个没有元素的空的List:

    1. >>> val list:List<Int> = listOf()
    2. >>> list
    3. []
    4. >>> list::class
    5. class kotlin.collections.EmptyList

    注意,这里的变量的类型不能省略,否则会报错:

    1. >>> val list = listOf()
    2. error: type inference failed: Not enough information to infer parameter T in inline fun <T> listOf(): List<T>
    3. Please specify it explicitly.
    4. val list = listOf()
    5. ^

    因为这是一个泛型函数。关于泛型,我们将在下一章中介绍。

    其中,EmptyList 是一个 internal object EmptyList, 这是Kotlin内部定义的一个默认空的object List类。

    下面,我们再来创建一个只有1个元素的List:

    1. >>> val list = listOf(1)
    2. >>> list::class
    3. class java.util.Collections$SingletonList

    我们可以看出,它实际上是调用Java的java.util.Collections 里面的singletonList方法:

    1. public static <T> List<T> singletonList(T o) {
    2. return new SingletonList<>(o);
    3. }
    1. >>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)
    2. >>> list
    3. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    4. >>> list::class
    5. class java.util.Arrays$ArrayList
    6. >>> list::class.java

    它调用的是

    1. fun <T> listOf(vararg elements: T): List<T> = if (elements.size > 0) elements.asList() else emptyList()

    这个函数。其中,asList函数是Array的扩展函数:

    1. public fun <T> Array<out T>.asList(): List<T> {
    2. return ArraysUtilJVM.asList(this)
    3. }

    而这个ArraysUtilJVM是一个Java类,里面实际上调用的是java.util.Arraysjava.util.List :

    另外,我们还可以直接使用arrayListOf函数来创建一个Java中的ArrayList对象实例:

    1. >>> val list = arrayListOf(0,1,2,3)
    2. >>> list
    3. [0, 1, 2, 3]
    4. >>> list::class
    5. class java.util.ArrayList
    6. >>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)
    7. >>> list::class
    8. class java.util.Arrays$ArrayList

    这个函数定义在libraries/stdlib/src/kotlin/collections/Collections.kt类中:

    1. @SinceKotlin("1.1")
    2. @kotlin.internal.InlineOnly
    3. public inline fun <T> arrayListOf(): ArrayList<T> = ArrayList()

    同样的处理方式,这里的 ArrayList() 是Java中的 java.util.ArrayList 的类型别名:

    1. @SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>

    在MutableList中,除了继承List中的那些函数外,另外新增了add/addAll、remove/removeAll/removeAt、set、clear、retainAll等更新修改的操作函数。

    1. override fun add(element: E): Boolean
    2. override fun remove(element: E): Boolean
    3. fun addAll(index: Int, elements: Collection<E>): Boolean
    4. override fun retainAll(elements: Collection<E>): Boolean
    5. override fun clear(): Unit
    6. operator fun set(index: Int, element: E): E
    7. fun add(index: Int, element: E): Unit
    8. fun removeAt(index: Int): E
    9. override fun listIterator(): MutableListIterator<E>
    10. override fun listIterator(index: Int): MutableListIterator<E>
    11. override fun subList(fromIndex: Int, toIndex: Int): MutableList<E>

    创建一个MutableList的对象实例跟List类似,前面加上前缀mutable,代码示例如下:

    1. >>> val list = mutableListOf(1, 2, 3)
    2. >>> list
    3. [1, 2, 3]
    4. >>> list::class
    5. class java.util.ArrayList
    6. >>> val list2 = mutableListOf<Int>()
    7. >>> list2
    8. []
    9. >>> list2::class
    10. class java.util.ArrayList
    11. >>> val list3 = mutableListOf(1)
    12. >>> list3
    13. [1]
    14. >>> list3::class
    15. class java.util.ArrayList

    我们可以看出,使用mutableListOf函数创建的可变集合类,实际上背后调用的是java.util.ArrayList类的相关方法。

    另外,我们可以直接使用Kotlin封装的arrayListOf函数来创建一个ArrayList:

    1. >>> val list4 = arrayListOf(1, 2, 3)
    2. >>> list4::class
    3. class java.util.ArrayList

    关于Kotlin中的ArrayList类型别名定义在 kotlin/collections/TypeAliases.kt 文件中:

    1. @file:kotlin.jvm.JvmVersion
    2. package kotlin.collections
    3. @SinceKotlin("1.1") public typealias RandomAccess = java.util.RandomAccess
    4. @SinceKotlin("1.1") public typealias ArrayList<E> = java.util.ArrayList<E>
    5. @SinceKotlin("1.1") public typealias LinkedHashMap<K, V> = java.util.LinkedHashMap<K, V>
    6. @SinceKotlin("1.1") public typealias HashMap<K, V> = java.util.HashMap<K, V>
    7. @SinceKotlin("1.1") public typealias LinkedHashSet<E> = java.util.LinkedHashSet<E>
    8. @SinceKotlin("1.1") public typealias HashSet<E> = java.util.HashSet<E>
    9. // also @SinceKotlin("1.1")
    10. internal typealias SortedSet<E> = java.util.SortedSet<E>
    11. internal typealias TreeSet<E> = java.util.TreeSet<E>

    如果我们已经有了一个不可变的List,而我们现在想把他转换成可变的List,我们可以直接调用转换函数toMutableList

    使用Iterator迭代器

    我们以集合 val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)为例,使用Iterator迭代器遍历列表所有元素的操作:

    1. >>> val list = listOf(0,1, 2, 3, 4, 5, 6,7,8,9)
    2. >>> list
    3. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    4. >>> val iterator = list.iterator()
    5. >>> iterator
    6. java.util.AbstractList$Itr@438bad7c
    7. >>> while(iterator.hasNext()){
    8. ... println(iterator.next())
    9. ... }
    10. 0
    11. 1
    12. 3
    13. 5
    14. 6
    15. 7
    16. 8
    17. 9

    Kotlin中的Iterator功能比较简单,并且只能单向移动:

    (1)调用iterator()函数,容器返回一个Iterator实例。iterator()函数是kotlin.collections.Iterable中的函数, 被Collection继承。
    (2)调用hasNext()函数检查序列中是否还有元素。
    (3)第一次调用Iterator的next()函数时,它返回序列的第一个元素。依次向后递推,使用next()获得序列中的下一个元素。

    当我们调用到最后一个元素,再次调用next()函数,会抛这个异常java.util.NoSuchElementException。代码示例:

    1. >>> val list = listOf(1,2,3)
    2. >>> val iter = list.iterator()
    3. >>> iter
    4. java.util.AbstractList$Itr@3abfe845
    5. >>> iter.hasNext()
    6. true
    7. >>> iter.next()
    8. 1
    9. >>> iter.hasNext()
    10. true
    11. >>> iter.next()
    12. 2
    13. >>> iter.hasNext()
    14. true
    15. >>> iter.next()
    16. 3
    17. >>> iter.hasNext()
    18. false
    19. >>> iter.next()
    20. java.util.NoSuchElementException
    21. at java.util.AbstractList$Itr.next(AbstractList.java:364)

    我们可以看出,这里的Iterator的实现是在AbstractList中的内部类IteratorImpl

    1. private open inner class IteratorImpl : Iterator<E> {
    2. protected var index = 0
    3. override fun hasNext(): Boolean = index < size
    4. override fun next(): E {
    5. if (!hasNext()) throw NoSuchElementException()
    6. return get(index++)
    7. }
    8. }

    通过这个实现源码,我们可以更加清楚地明白Iterator的工作原理。

    其中,NoSuchElementException()这个类是java.util.NoSuchElementException的类型别名:

    1. @kotlin.SinceKotlin public typealias NoSuchElementException = java.util.NoSuchElementException

    使用forEach遍历List元素

    这个forEach函数定义如下:

    1. @kotlin.internal.HidesMembers
    2. public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
    3. for (element in this) action(element)
    4. }

    它是package kotlin.collections包下面的Iterable的扩展内联函数。它的入参是一个函数类型:

    1. action: (T) -> Unit

    关于函数式编程,我们将在后面章节中学习。

    这里的forEach是一个语法糖。实际上forEach在遍历List对象的时候,仍然使用的是iterator迭代器来进行循环遍历的。

    1. >>> val list = listOf(1,2,3)
    2. >>> list
    3. [1, 2, 3]
    4. >>> list.forEach{
    5. ... println(it)
    6. ... }
    7. 1
    8. 2
    9. 3

    当参数只有一个函数的时候,括号可以省略不写。

    也就是说,这里面的forEach函数调用的写法,实际上跟下面的写法等价:

    我们甚至还可以直接这样写: