抽象了遍历过程:迭代器模式将遍历过程抽象为一个独立的迭代器对象,封装了遍历的细节和逻辑。这样,可以通过迭代器对象来遍历集合,而无需直接操作集合本身。这样做的好处是,可以隐藏集合的内部实现细节,提供一种统一的遍历接口,使代码更加模块化和可维护。
支持不同类型的集合:迭代器模式可以适用于不同类型的集合,包括自定义的数据结构。通过实现迭代器接口,可以定义不同集合的迭代器,使它们具有相同的遍历方式和接口。这样,可以在不改变遍历代码的情况下,切换不同类型的集合或数据结构。
支持并发遍历:在某些情况下,可能需要在多个线程中同时遍历集合。使用迭代器模式,可以创建线程安全的迭代器,确保在并发环境下遍历的正确性和一致性。
支持遍历过程中的操作:迭代器模式允许在遍历过程中执行操作,如删除元素或修改集合。通过迭代器的remove()方法,可以安全地删除集合中的元素,而不会导致遍历过程中的异常或错误。
迭代器(Iterator):它是一个接口或抽象类,定义了遍历集合对象的方法,例如hasNext()用于检查是否还有下一个元素,next()用于获取下一个元素。
interface Iterator<T> {
fun hasNext(): Boolean
fun next(): T
}
集合(Collection):它是一个包含元素的集合对象,可以是一个列表、数组或其他数据结构。集合提供了创建迭代器的方法,例如iterator()。
interface Collection<T> {
fun iterator(): Iterator<T>
}
通过实现迭代器接口和集合接口,我们可以创建可迭代的集合,并使用迭代器逐个访问集合中的元素:
class MyCollection<T>(private val items: List<T>) : Collection<T> {
override fun iterator(): Iterator<T> {
return MyIterator()
}
private inner class MyIterator : Iterator<T> {
private var currentIndex = 0
override fun hasNext(): Boolean {
return currentIndex < items.size
}
override fun next(): T {
if (!hasNext()) {
throw NoSuchElementException()
}
return items[currentIndex++]
}
}
}
// 使用迭代器遍历集合
val collection = MyCollection(listOf(1, 2, 3, 4, 5))
val iterator = collection.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
println(item)
}
或许很多小伙伴会认为迭代器可有可无,毕竟一个for循环就能搞定的事,何必这么麻烦呢?
设计模式设计出来那就是用来解决问题的,不知道大家有没有遇到这个问题:当我们一边遍历一个可修改的列表的时候,一边移除列表的元素的话,使用for循环是会报错的。迭代器就很好地适配这个问题,一般像Kotlin语言的list自带有lterator。但在这里我们来看看轮子的大概:
interface Iterator<T> {
fun hasNext(): Boolean
fun next(): T
fun remove()
}
interface Collection<T> {
fun iterator(): Iterator<T>
}
class MyCollection<T>(private val items: MutableList<T>) : Collection<T> {
override fun iterator(): Iterator<T> {
return MyIterator()
}
private inner class MyIterator : Iterator<T> {
private var currentIndex = 0
private var lastReturnedIndex = -1
override fun hasNext(): Boolean {
return currentIndex < items.size
}
override fun next(): T {
if (!hasNext()) {
throw NoSuchElementException()
}
lastReturnedIndex = currentIndex
return items[currentIndex++]
}
override fun remove() {
if (lastReturnedIndex == -1) {
throw IllegalStateException()
}
items.removeAt(lastReturnedIndex)
currentIndex--
lastReturnedIndex = -1
}
}
}
fun main() {
// 使用迭代器遍历集合
val collection = MyCollection(mutableListOf(1, 2, 3, 4, 5))
val iterator = collection.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
println(item)
if (item == 3) {
iterator.remove()
}
}
println(collection.items) // prints [1, 2, 4, 5]
}
似乎还是用处不大,那如果加上多线程呢?
import java.util.concurrent.locks.ReentrantReadWriteLock
class MyCollection<T>(private val items: MutableList<T>) : Collection<T> {
private val lock = ReentrantReadWriteLock()
override fun iterator(): Iterator<T> {
return MyIterator()
}
private inner class MyIterator : Iterator<T> {
private var currentIndex = 0
private var lastReturnedIndex = -1
override fun hasNext(): Boolean {
lock.readLock().lock()
try {
return currentIndex < items.size
} finally {
lock.readLock().unlock()
}
}
override fun next(): T {
lock.readLock().lock()
try {
if (!hasNext()) {
throw NoSuchElementException()
}
lastReturnedIndex = currentIndex
return items[currentIndex++]
} finally {
lock.readLock().unlock()
}
}
override fun remove() {
lock.writeLock().lock()
try {
if (lastReturnedIndex == -1) {
throw IllegalStateException()
}
items.removeAt(lastReturnedIndex)
currentIndex--
lastReturnedIndex = -1
} finally {
lock.writeLock().unlock()
}
}
}
fun add(item: T) {
lock.writeLock().lock()
try {
items.add(item)
} finally {
lock.writeLock().unlock()
}
}
fun remove(item: T) {
lock.writeLock().lock()
try {
items.remove(item)
} finally {
lock.writeLock().unlock()
}
}
fun size(): Int {
lock.readLock().lock()
try {
return items.size
} finally {
lock.readLock().unlock()
}
}
}
fun main() {
// 使用迭代器遍历集合
val collection = MyCollection(mutableListOf(1, 2, 3, 4, 5))
val iterator = collection.iterator()
while (iterator.hasNext()) {
val item = iterator.next()
println(item)
if (item == 3) {
iterator.remove()
}
}
println(collection.size()) // prints 4
// 在多个线程中添加和删除元素
val thread1 = Thread {
collection.add(6)
collection.add(7)
}
val thread2 = Thread {
collection.remove(4)
collection.remove(5)
}
thread1.start()
thread2.start()
thread1.join()
thread2.join()
println(collection.size()) // prints 4
}
那么我们在经常使用的RecyclerView中将数据源collection替换成collection.iterator()的话,不就能支持多线程了哇。
Thank you for your reading, best regards!