5.3.3 遍历List元素
使用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. 2
13. 3
14. 4
15. 5
16. 6
17. 7
18. 8
19. 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
2. ```#### 使用`forEach`遍历List元素
4. 这个`forEach`函数定义如下:
6. ```kotlin
7. @kotlin.internal.HidesMembers
8. public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
9. for (element in this) action(element)
10. }
它是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函数调用的写法,实际上跟下面的写法等价:
1. list.forEach({
2. println(it)
3. })
我们甚至还可以直接这样写:
1. >>> list.forEach(::println)
其中,:: 是函数引用符。
