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元素
  3. 这个`forEach`函数定义如下:
  4. ```kotlin
  5. @kotlin.internal.HidesMembers
  6. public inline fun <T> Iterable<T>.forEach(action: (T) -> Unit): Unit {
  7. for (element in this) action(element)
  8. }

它是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)

其中,:: 是函数引用符。