加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala:有没有理由喜欢`filter map` over`collect`?

发布时间:2020-12-16 18:58:25 所属栏目:安全 来源:网络整理
导读:有什么理由可以选择过滤图: list.filter (i = aCondition(i)).map(i = fun(i)) 收集? : list.collect(case i if aCondition(i) = fun(i)) 收集(单一看)的一个看起来更快,更干净.所以我会永远去收集. 解决方法 大多数Scala的集合都热切地应用操作,(除非你
有什么理由可以选择过滤图:

list.filter (i => aCondition(i)).map(i => fun(i))

收集? :

list.collect(case i if aCondition(i) => fun(i))

收集(单一看)的一个看起来更快,更干净.所以我会永远去收集.

解决方法

大多数Scala的集合都热切地应用操作,(除非你使用一个为你这样做的宏库)不会融合操作.所以过滤跟踪的地图通常会创建两个集合(即使你使用了Iterator或者somesuch,中间的形式将被暂时创建,尽管只是一次一个元素),而collect不会.

另一方面,collect使用部分函数实现联合测试,部分函数在测试集合中是否存在时比谓词(A => Boolean)慢.

此外,可能会有一些情况比其他情况更清楚,您不关心性能或内存使用差异在2左右.在这种情况下,使用更清楚的一个.一般来说,如果你已经有了命名的功能,那么它更清楚的读取

xs.filter(p).map(f)
xs.collect{ case x if p(x) => f(x) }

但是如果您在线提供闭包,收集通常看起来更干净

xs.filter(x < foo(x,x)).map(x => bar(x,x))
xs.collect{ case x if foo(x,x) => bar(x,x) }

即使它不一定更短,因为你只是参考一次变量.

现在,性能差异有多大?这有所不同,但如果我们考虑一个这样的集合:

val v = Vector.tabulate(10000)(i => ((i%100).toString,(i%7).toString))

并且您想要基于过滤第一个条目选择第二个条目(因此,过滤器和映射操作都非常简单),那么我们将得到下表.

注意:可以将收藏的懒惰视图收集起来,并在那里收集操作.您并不总是将您的原始类型返回,但您可以随时使用来获取正确的收藏类型.所以xs.view.filter(p).map(f).toVector会因为这个视图而不会创建一个中间件.这也是下面测试的.也有人建议,可以xs.flatMap(x => if(p(x))Some(f(x))else None),这是有效的.那不是这样.它也在下面测试.并且可以通过显式创建构建器来避免部分功能:val vb = Vector.newBuilder [String]; xs.foreach(x => if(p(x))vb = f(x)); vb.result,其结果也列在下面.

在下表中,已经测试了三个条件:过滤掉任何东西,过滤掉一半,过滤出所有内容.时间已经归一化为过滤器/映射(100%=与过滤器/映射相同的时间,较低).误差范围在-3%左右.

不同过滤器/地图替代品的性能

====================== Vector ========================
filter/map   collect  view filt/map  flatMap   builder
   100%        44%          64%        440%      30%    filter out none
   100%        60%          76%        605%      42%    filter out half
   100%       112%         103%       1300%      74%    filter out all

因此,过滤器/映射和收集通常非常接近(当您保持很多时,收集获胜),flatMap在所有情况下都要慢得多,并且创建构建器总是胜利. (对于Vector来说,这是真的,其他的集合可能有些不同的特征,但大多数的趋势将是相似的,因为操作的差异是相似的.)这个测试中的观点往往是一个胜利,但是它们并不总是工作无缝地(除了空的情况,它们并不比收集更好).

所以,底线:喜欢过滤器,然后映射,如果它有助于清晰度,当速度无关紧要,或喜欢它的速度,当你过滤掉几乎所有的东西,但仍然希望保持功能(所以不想使用建设者);否则使用收集.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读