2011-08-09 63 views
23

我有一张地图需要映射到不同的类型,结果需要是列表。我有两种方式(看似)来完成我想要的功能,因为在地图上调用地图似乎总是导致地图。假设我有一些地图,看起来像:将斯卡拉地图转换为列表

val input = Map[String, List[Int]]("rk1" -> List(1,2,3), "rk2" -> List(4,5,6)) 

我可以这样做:

val output = input.map{ case(k,v) => (k.getBytes, v) } toList 

或者:

val output = input.foldRight(List[Pair[Array[Byte], List[Int]]]()){ (el, res) => 
    (el._1.getBytes, el._2) :: res 
} 

在我转换类型的第一个实例,然后调用toList 。我假设运行时间类似于O(n*2),所需空间为n*2。在第二个例子中,我转换类型并一次性生成列表。我假设运行时间为O(n),所需空间为n

我的问题是,这些是基本相同的还是第二次转换减少内存/时间/等?此外,我在哪里可以找到有关各种scala转换的存储和运行时成本的信息?

在此先感谢。

回答

23

我最喜欢的方式做这样的事情是这样的:

input.map { case (k,v) => (k.getBytes, v) }(collection.breakOut): List[(Array[Byte], List[Int])] 

有了这个语法,要传递到map它需要重建的结果集合建设者。 (实际上,不是一个建造者,而是一个建造者工厂。如果您有兴趣,请阅读更多有关Scala的CanBuildFrom的信息。)collection.breakOut可以在您想从一个集合类型更改为另一个集合时使用mapflatMap等。唯一不好的部分是你必须使用完整的类型注释才能生效(这里,我在表达式之后使用了类型归属)。然后,没有建立中间集合,并且构建列表,而映射。

+3

1。对于那些试图了解'breakOut'如何工作的人,请参阅Daniel Sobral的优秀答案,http://stackoverflow.com/questions/1715681/scala-2-8-breakout/1716558#1716558 –

18

映射在在第一实施例的图可以削减所需的空间为大地图:

val output = input.view.map{ case(k,v) => (k.getBytes, v) } toList 
+0

关于懒惰视图:http:// www .scala-lang.org /实况/文件/集合-API/collections_42.html – Vadzim