这儿每天共享一个 iOS 的新知识,快来重视我吧
前语
我相信大多数人听过慵懒调集(lazy collections
),可是却很少用到。慵懒调集与常规调集功能相似,但它改变了 map
、 filter
和 reduce
等高阶函数的处理方式。在某些状况下运用慵懒调集能够提高应用的功能。
今天的文章主要来介绍一下如何运用慵懒调集。
lazy collection
慵懒调集也是调集的一种,只不过它在进行某些核算的时分会推延进行,比如数组的遍历取值时,它往往不会直接遍历一切的元素,而是直到真正用到某个元素的时分才会履行,这在许多不同的状况下都是有益的,而且能够防止很多不用的功能开销。
咱们先来举个比如,有一个数字调集,我需求先把偶数筛选出来,再把筛选出的成果乘以 2,终究得到成果。正常的代码是这样的:
var numbers: [Int] = [1, 2, 3, 4]
let modifiedNumbers = numbers
.filter { number in
print("履行了 filter")
return number % 2 == 0
}.map { number -> Int in
print("履行了 map")
return number * 2
}
print(modifiedNumbers)
// 打印成果
//履行了 filter
//履行了 filter
//履行了 filter
//履行了 filter
//履行了 map
//履行了 map
//[4, 8]
履行的成果契合咱们的预期,先把 numbers
每个元素走了一遍 filter
,过滤出偶数(2 和 4),然后再用 map
函数把过滤出的两个数乘 2,终究成果是 [4, 8]。
接下来咱们用慵懒调集重写这块代码,运用慵懒调集只需求在调集后加上 .lazy
关键字:
let modifiedNumbers = numbers
.lazy
.filter { number in
print("履行了 filter")
return number % 2 == 0
}.map { number -> Int in
print("履行了 map")
return number * 2
}
print(modifiedNumbers)
// 打印成果
//LazyMapSequence<LazyFilterSequence<Array<Int>>, Int>(_base: Swift.LazyFilterSequence<Swift.Array<Swift.Int>>(_base: [1, 2, 3, 4], _predicate: (Function)), _transform: (Function))
从成果能够看出,终究打印了一个 LazyMapSequence<LazyFilterSequence<Array<Int>>
目标,而 filter
和 map
的循环一次都没有走进去。原因正是咱们上边提到的,运用 lazy 之后只要真正用到某个元素的时分才会履行。
咱们尝试打印成果中的第一个值:
print(modifiedNumbers.first)
// 打印成果
//履行了 filter
//履行了 filter
//履行了 map
//Optional(4)
从打印成果能够看出,当咱们获取第一个值的时分,先走了两次 filter
,找出第一个契合条件的数字 2,然后走了一次 map
把终究成果算出来 4。如果咱们仅仅是想获取成果中的第一个值,那么运用 lazy
的功能要比不运用 lazy
好的多,尤其是数组非常大的时分。
什么时分应该运用慵懒调集
也不是一切状况都合适运用慵懒调集,比如当你的数组中元素不多时,其实用不用慵懒调集功能都不会有差别,理论上来说只要当你调集非常大,而你又只需求运用一小部分数据(不需求每个都核算一遍)的时分运用慵懒调集比较合适。
还有一种状况是当核算的下流还有其他函数时,它会把上游每一个核算出的值优先走下流的函数,比如你要过滤出 0 – 100000000 之间一切的偶数,并乘以 2,这是很慢的进程。而 lazy 的行为是每次核算出一个偶数就会履行一下乘以 2 的操作,而不是把一切值核算完成后再乘 2,适用于边核算边出成果的状况。
还有一点需求留意,慵懒调集核算出的成果并不会缓存,就以咱们上边的代码为例,你每次调用 modifiedNumbers.first
都会履行两次 filter
和一次 map
。这时分如果你想重复运用核算出的值,就需求你先把成果缓存起来,下次运用直接运用缓存值,防止重新核算一次。
本文同步自微信公众号 “iOS新知”,每天按时共享一个新知识,这儿只是同步,想要及时学到就来重视我吧!