Lazy collections feature in Swift

深入理解代替单纯记忆

当前最新Swift版本为Swift 5.10

之前一直没注意过Lazy Collection这个Swift特性,最近在看Design protocol interfaces in Swift-WWDC时偶然看到,查阅了一下资料,发现这个特性很早就有了,早在WWDC2018时官方在Using Collections Effectively session中就提到了

先对该特性做一个概括性的描述:

  • 该特性是Sequence protocol的一个属性---var lazy: LazySequence<Self> { get }
  • 该属性返回的值同样描述了一个Sequence,虽然元素和原Sequence是相同的
  • 但对返回的Sequence进行各种高阶函数操作时(如map、reduce、filter等等),就拥有了lazy(延迟计算)能力
  • 所谓延迟计算的特性,可以理解为,直到真正需要用到集合中的元素时(而非在此之前的某个时机),才会真正去遍历或读取集合中的元素,且尽可能只读取所需要的元素,避免多余的读取操作

我把官方文档中对lazy属性的描述原文贴出来:

A sequence containing the same elements as this sequence, but on which some operations, such as map and filter, are implemented lazily.

我认为其实但看上面的内容是比较难描述lazy的能力,通过下面的两个例子可以更容易理解

Demo1

swift 复制代码
let array = [1, 2, 3]

let mappedArray = array.map({
    print("map on array --- \($0)")
    return $0
})


let lazyMappedArray = array.lazy.map({
    print("map on lazy array --- \($0)")
    return $0
})

print(lazyMappedArray.first)

控制台输出结果为

c 复制代码
map on array --- 1
map on array --- 2
map on array --- 3
map on lazy array --- 1
Optional(1)

以上例子得出的结论是:

  • 普通的集合,在没有lazy能力加持下,当执行到array.map时就会对集合所有元素进行遍历
  • 有了lazy能力加持后,array.lazy.map执行时,map中的closure完全不会执行
  • 直到执行到lazyMappedArray.first时,map的closure才会执行。而且并不会遍历整个array,仅对第一个元素执行了closure

Demo2

另一个场景是,有些时候我们需要声明一个Readonly的属性,返回一个集合,

  • 该集合的创建可能需要遍历一个已有的集合
  • Readonly的属性可能需要在程序整个生命周期中执行多次,每次使用都会执行上面的逻辑
swift 复制代码
struct ABC {
    let array = [1, 2, 3]
    var mappedArray: [Int] {
        return array.map {
            print("map on array --- \($0)")
            return $0
        }
    }
    
    var lazyMappedArray:  LazyMapSequence<LazySequence<[Int]>.Elements, LazySequence<[Int]>.Element> {
        return array.lazy.map({
            print("map on lazy array --- \($0)")
            return $0
        })
    }
}

let abc = ABC()
var mappedArray = abc.mappedArray
var lazyMappedArray = abc.lazyMappedArray
abc.mappedArray
abc.lazyMappedArray

lazyMappedArray.first
lazyMappedArray.first

控制台输出结果是

sql 复制代码
map on array --- 1
map on array --- 2
map on array --- 3
map on array --- 1
map on array --- 2
map on array --- 3

map on lazy array --- 1
map on lazy array --- 1
  • 每次执行abc.mappedArray,array都会被遍历一遍
  • abc.lazyMappedArray则不会去遍历array,因为还没有使用lazyMappedArray中的元素
  • lazyMappedArray.first尝试读取集合元素时,才会真正执行map closure逻辑

总结

  • Lazy collection特性是通过Sequencelazy属性来提供给开发者使用,所以实现了Sequence协议的类型都支持lazy能力
  • 所谓延迟计算的特性,可以理解为,直到真正需要用到集合中的元素时(而非在此之前的某个时机),才会真正去遍历或读取集合中的元素,且尽可能只读取所需要的元素,避免多余的读取操作
  • lazy所赋予的延迟计算能力,在仅使用大数据量集合的部分元素、创建临时集合场景时,能显著降低额外性能损耗

参考

相关推荐
良技漫谈1 天前
Rust移动开发:Rust在iOS端集成使用介绍
后端·程序人生·ios·rust·objective-c·swift
KeithTsui2 天前
ZFC in LEAN 之 前集的等价关系(Equivalence on Pre-set)详解
开发语言·其他·算法·binder·swift
袁代码2 天前
Swift 开发教程系列 - 第4章:函数与闭包
ios·swift·ios开发
安泽13143 天前
高德地图美食
开发语言·swift·美食
袁代码3 天前
Swift 开发教程系列 - 第2章:Swift 基础语法
swift·ios开发·基础教程
袁代码3 天前
Swift 开发教程系列 - 第1章:Swift 简介与开发环境配置
swift·ios开发·基础教程
孚亭4 天前
一些swift问题
swift
莫问alicia4 天前
echarts 实现3D饼状图 加 label标签显示
前端·3d·echarts·swift
uiop_uiop_uiop6 天前
iOS Swift5算法恢复——HMAC
ios·iphone·swift
東三城8 天前
【ios】---SwiftUI开发从入门到放弃
ios·swiftui·swift·1024程序员节