我正在将一个项目从 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
可能是我,但即使在阅读了这些参考资料之后,对于大多数(如果不是全部)用例,我也没有发现使用视图的明显优势。还有比我更开明的人吗?