Scala 2.13 视图与 LazyList

2024-02-10

我正在将一个项目从 Scala 2.12.1 迁移到 2.13.6,并发现SeqView#flatMap现在返回一个View,其中没有distinct方法。因此,我有一段代码不再编译:

val nodes = debts.view
      .flatMap { case Debt(from, to, _) => List(from, to) }
      .distinct
      .map(name => (name, new Node(name)))
      .toMap

有一个愚蠢的方法来修复它,将视图转换为 seq,然后再转换回视图:

val nodes = debts.view
      .flatMap { case Debt(from, to, _) => List(from, to) }.toSeq.view
      .distinct
      .map(name => (name, new Node(name)))
      .toMap

然而,这显然不太好,因为它强制收集视图,而且必须在类型之间来回切换也是非常不优雅的。我找到了另一种方法来修复它,就是使用LazyList:

val nodes = debts.to(LazyList)
      .flatMap { case Debt(from, to, _) => List(from, to) }
      .distinct
      .map(name => (name, new Node(name)))
      .toMap

这就是我想要的,它基本上表现得像 Java 流。当然,有些操作有O(n)内存使用情况如distinct,但至少其后的所有操作都可以进行流式传输,而无需重建数据结构。

有了这个,它让我思考为什么我们应该需要一个视图,因为它们的功能比以前要小得多(即使我可以相信 2.13 已经解决了这个功能引入的一些其他问题)。我寻找答案并找到提示,但我发现没有足够全面的内容。以下是我的研究:

  • 2.13中视图的说明 https://docs.scala-lang.org/overviews/collections-2.13/views.html
  • 堆栈溢出:List.view 和 LazyList 有什么区别? https://stackoverflow.com/questions/59587449/what-is-the-difference-between-list-view-and-lazylist
  • 另一个外部网站的比较 http://www.baeldung.com/scala/stream-vs-views-vs-iterators

可能是我,但即使在阅读了这些参考资料之后,对于大多数(如果不是全部)用例,我也没有发现使用视图的明显优势。还有比我更开明的人吗?


Scala 2.13 中的惰性序列实际上有 3 种基本可能性:View、Iterator 和 LazyList。

View是最简单的惰性序列,几乎没有额外的成本。一般情况下最好使用默认值,以避免在处理大型序列时分配中间结果。

可以多次遍历视图(使用 foreach、foldLeft、toMap 等)。每次遍历都会单独执行转换(map、flatMap、filter 等)。因此必须小心避免耗时的转换,或者只遍历视图一次。

Iterator只能遍历一次。它类似于 Java Streams 或 Python 生成器。 Iterator 上的大多数转换方法都要求您仅使用返回的 Iterator 并丢弃原始对象。

它也像视图一样快,并且支持更多操作,包括不同的操作。

LazyList基本上是一个真正严格的结构,可以动态自动扩展。 LazyList 会记住所有生成的元素。如果你有一个val使用 LazyList,将为所有生成的元素分配内存。但是如果你动态遍历它并且不存储在val,垃圾收集器可以清理遍历到的元素。

Scala 2.12 中的流比视图或迭代器慢得多。我不确定这是否适用于 Scala 2.13 中的 LazyList。


所以每个惰性序列都有一些警告:

  • 视图可以多次执行转换。
  • 迭代器只能被使用一次。
  • LazyList可以为所有序列元素分配内存。

我相信在您的用例中,迭代器是最合适的:

val nodes = debts.iterator
      .flatMap { case Debt(from, to, _) => List(from, to) }
      .distinct
      .map(name => (name, new Node(name)))
      .toMap
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scala 2.13 视图与 LazyList 的相关文章

  • Scala 模式与 TypeTag 的泛型匹配会生成警告,而 ClassTag 不会?

    我有两种非常相似的方法 唯一的区别是使用ClassTag and TypeTag def matchClass A ClassTag v Any v match case a A gt it s A case gt not A def ma
  • Spark Collect_list 并限制结果列表

    我有以下格式的数据框 name merged key1 internalKey1 value1 key1 internalKey2 value2 key2 internalKey3 value3 我想做的是将数据框分组name 收集列表并l
  • Scala Monad - 完整的示例[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 将 Scala 文件转换为 Dll

    我有一些使用 IntelliJ 和 SBT Plugin 编写的 scala 代码 并希望将代码作为 C 的 DLL 提供给我 我已经尝试使用 ikvmc 我通过 package 将所有类打包在一个罐子中 之后 我手动设置一个 jar 其中
  • Scala中如何将DataFrame转换为RDD?

    有人可以分享一下如何转换dataframe to an RDD Simply val rows RDD Row df rdd
  • 不使用 CPU 时 Cassandra 超时

    我使用 Phantom DSL 和 Datastax Cassandra 驱动程序时遇到 Cassandra 超时 然而 Cassandra 似乎并没有超载 以下是我得到的异常 com datastax driver core except
  • 将列表拆分为多个具有固定元素数量的列表

    如何将元素列表拆分为最多包含 N 个项目的列表 例如 给定一个包含 7 个元素的列表 创建 4 个组 最后一组可能包含较少的元素 split List 1 2 3 4 5 6 seven 4 gt List List 1 2 3 4 Lis
  • Spark:用列的平均值替换数据框中的空值

    如何创建 UDF 以编程方式将每列中 Spark 数据框中的空值替换为列平均值 例如 在示例中 数据 col1 空值的值为 2 4 6 8 5 5 5 示例数据 col1 col2 col3 2 null 3 4 3 3 6 5 null
  • Scala 组合器解析器 - 区分数字字符串和变量字符串

    我正在做 Cay Horstmann 的组合器解析器练习 我想知道区分代表数字的字符串和代表匹配语句中变量的字符串的最佳方法 def factor Parser ExprTree wholeNumber expr ident case a
  • IntelliJ IDEA Scala 插件问题

    我对新的 Intellij IDEA 10 和 Scala 插件有疑问 当我在 Scala 源文件中输入任何内容时 编辑器会永久冻结 在其他文件 java 和其他 编辑器中效果很好 结构视图 scala 检查和显示成员功能已关闭 堆大小增加
  • 如何检查字符串中是否包含某个字符?

    我想检查字符串是否包含该字符 我正在编写一个刽子手代码 例如 下面是要猜测的单词 scala 但看起来像 至用户 假设用户输入字母 a 那么它一定看起来像 a a def checkGuess if result contains user
  • 了解如何使用 apply 和 unappy

    我试图更好地理解 的正确用法apply and unapply方法 考虑到我们想要序列化和反序列化的对象 这是正确的用法吗 即斯卡拉方式 的使用apply and unapply case class Foo object Foo appl
  • 如何使用 apply/unapply 方法重现案例类行为?

    我尝试用普通类和伴生对象替换案例类 但突然出现类型错误 编译良好的代码 综合示例 trait Elem A B def C other Elem C A Elem C B other match case Chain head tail g
  • Scala:具有复杂结构的树插入尾递归

    我正在 scala 中创建自定义对象树 并且我的插入方法引发堆栈溢出 因为它不是尾递归 但是 我不太清楚如何使其尾递归 我见过使用 累加器 变量的相关示例 但它们要么是只能相乘和覆盖的整数之类的东西 要么是我在适应树时遇到困难的列表 这是我
  • Scala Array.apply 有何魔力

    来自 scala 2 10 4 的 array scala Array定义为 final class Array T length Int extends java io Serializable with java lang Clonea
  • 使用原始类型模拟案例类

    考虑以下类型结构 trait HasId T def id T case class Entity id Long extends HasId Long 比方说 我们想在一些测试中模拟实体类 val entityMock mock Enti
  • Scala 如何忽略 Java 的检查异常?

    例如如果调用 JavaThread sleep这会抛出一个已检查的InterruptedException来自 Scala 源文件 然后不需要将调用包含在 Scala 中try catch Scala 如何删除将调用包围在 a 中的规则tr
  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • 使用 Spark DataFrame 获取组后所有组的 TopN

    我有一个 Spark SQL DataFrame user1 item1 rating1 user1 item2 rating2 user1 item3 rating3 user2 item1 rating4 如何按用户分组然后返回TopN
  • 为什么《Scala 中的函数式编程》一书的“无异常处理错误”一章中没有提到“scala.util.Try”?

    在 Scala 中的函数式编程 一书中的 无异常处理错误 一章中 作者给出 从函数体抛出异常的问题 Use Option如果我们不关心实际的异常 Use Either如果我们关心实际的异常 But scala util Try没有提到 从我

随机推荐