Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Tuple2拉链与IterableLike拉链_Scala - Fatal编程技术网

Scala Tuple2拉链与IterableLike拉链

Scala Tuple2拉链与IterableLike拉链,scala,Scala,这两种实现之间有什么区别?一个比另一个好。 有一篇博文说Tuple2Zippped的性能更好,但没有提供原因,从源代码看,我看不出有什么不同 val l1 = List(1,2,3) val l2 = List(5,6,7) val v1 = l1 zip l2 val v2 = (l1, l2).zipped 如果不明显,v1和v2的值和类型不同:v1具有类型List[(Int,Int)]和值List((1,5)、(2,6)、(3,7))v2具有类型scala.runtime.Tuple2

这两种实现之间有什么区别?一个比另一个好。 有一篇博文说Tuple2Zippped的性能更好,但没有提供原因,从源代码看,我看不出有什么不同

val l1 = List(1,2,3)
val l2 = List(5,6,7)

val v1 = l1 zip l2
val v2 = (l1, l2).zipped

如果不明显,
v1
v2
的值和类型不同:
v1
具有类型
List[(Int,Int)]
和值
List((1,5)、(2,6)、(3,7))
v2
具有类型
scala.runtime.Tuple2Zipped[Int,List[Int],Int,List[Int]]
并且具有值
(List(1,2,3),List(5,6,7))。zipped

换句话说,
v1
的值是严格计算的(zip操作已经完成),而
v2
是延迟计算的(或非严格计算)——实际上,zip操作已经存储,但尚未执行

如果您只想计算这两个值(但不实际使用它们),那么我确实希望
v2
的计算速度更快,因为它实际上没有做很多工作。;-)

除此之外,这将取决于您随后打算如何使用这些值<如果您不需要处理结果列表中的每个元组,那么code>Tuple2Zipped将执行得更好,因为压缩不需要的列表元素不会浪费时间。如果您需要对每个元组应用一些操作,但不需要在处理后访问它们,因此只需通过一次列表,那么它可能有优势

如果需要对列表成员执行多个操作,并多次迭代,则
List.zip
方法可能是更好的选择

这两种方法都适用于所有情况。(在一般情况下,我更喜欢
List.zip
,因为
Tuple2Zipped
不太为人所知,而且它的使用会暗示一个特殊要求。)

如果性能确实是一个问题,那么我建议您在代码中对这两种方法进行基准测试,使用诸如和之类的工具准确区分这两种方法。我还建议对内存使用和处理时间进行基准测试,因为这两种方法有不同的内存需求

更新:在下面的评论中引用附加问题:“在
val m:Map[Int,Int]=(l1 zip l2)(突破)
(l1,l2).zip.toMap之间有区别吗?”

我将重申如下:

导入scala.collection.breakOut
val l1=列表(1、2、3)
val l2=列表(5、6、7)
//m1的类型必须是显式的,否则将推断为
//scala.collection.immutable.IndexedSeq[(Int,Int)]。
val m1:Map[Int,Int]=(l1压缩l2)(突破)
val m2=(l1,l2).zip.toMap
没有懒惰的
映射
,因为映射中的所有元素都需要可用,以便在内部构造映射,从而允许在执行键查找时有效地检索值

因此,严格评估的
(l1 zip l2)
和延迟评估的
(l1,l2).zip
之间的区别在转换为
映射时消失

那么哪一种更有效呢?在这个特定的例子中,我希望这两种方法的性能非常相似

当计算
m1
时,
zip
操作一次遍历
l1
l2
检查一对head元素。生成器(另请参见下面注释中的链接)和
Map[Int,Int]的声明结果类型
,导致
zip
操作生成一个
Map
,作为其结果(如果没有
breakOut
zip
将生成一个
列表[(Int,Int)]

总结这种方法,通过一次同时通过
l1
l2
创建结果图

(使用
breakOut
确实会有所不同。如果我们以
(l1-zip-l2.toMap
)的形式生成地图,那么我们通过
l1
l2
执行一次迭代来创建一个
列表[(Int,Int)]
,然后在该列表上迭代以创建生成的
地图;这显然效率较低

在新的Scala 13 collections API中,
breakOut
已被删除。但从类型角度来看,有一些新的替代方案工作得更好。有关更多详细信息,请参阅。)

现在让我们考虑<代码> M2。在这种情况下,如前面所述,<代码>(L1,L2).zipped

会产生一个元组惰性列表。但是,到目前为止,尚未对任何一个输入列表执行迭代。当执行
toMap
操作时,惰性列表中的每个元组在第一次引用时都会进行评估,并添加到正在构建的映射中

在总结这种方法时,再次通过一次同时通过
l1
l2
创建结果图


因此,在这个特定的用例中,这两种方法之间的差别将非常小。可能仍然有一些影响结果的次要实现细节,因此如果您在
l1
l2
中有大量数据,您可能仍然希望对它们进行基准测试以找到最佳解决方案。但是,我倾向于暗示选择
zip
操作(使用
breakOut
)并将其保持在该位置。

我的用例是将元组转换为映射。val m:map[Int,Int]=(l1-zip-l2)(breakOut)和(l1,l2)之间有区别吗.zipped.toMap?@EugeneMi有趣的问题!没有惰性映射,因为通过键查找值的能力需要了解整个集合。因此,当您将惰性集合转换为映射时,必须对其进行严格评估。因此,尽管
Tuple2Zipped
实例是惰性的,但每个元组都有奥贝