使用 immutable.ListMap 代替 mutable.LinkedHashMap

use*_*602 3 functional-programming scala

我想尽可能地使用不可变的数据结构。在我们的代码库中非常普遍的情况是使用mutable.LinkedHashMap。我想在所有非性能关键代码中用immutable.ListMap替换它。

我们的代码具有的通用格式

  1. mutable.LinkedHashMap 初始化
  2. 循环条件
  3. 基于某些条件在 LinkedHashMap 中添加元素
  4. 循环后,返回 LinkedHashMap

示例代码:

def dummyFunction(): mutable.LinkedHashMap[Int, String] = {
    val tmpListMap: mutable.LinkedHashMap[Int, String] = mutable.LinkedHashMap()
    for (i <- 1 to 10) {
        if (i%2 ==0) tmpListMap += (i -> "even")
        else tmpListMap += (i -> "odd")
    }
    tmpListMap
}
Run Code Online (Sandbox Code Playgroud)

我想在所有这些地方使用 ListMap。我不想再次循环 tmpListMap 来创建 ListMap。

斯卡拉版本:2.11

Dim*_*ima 5

你不知道如何返回一个不可变的映射,因为它创建后你不能修改它?这是问题吗?很多方法。例如:

(1 to 10).map { 
    case x if x%2 == 0 => (x -> "even")
    case x => (x -> "odd")
 }.toMap
Run Code Online (Sandbox Code Playgroud)

以上返回一个常规的Map,而不是ListMap。我不确定你为什么想要后者,但是,如果你出于某种原因这样做,那就有点复杂了:

 val tuples = (1 to 10).map { 
    case x if x%2 == 0 => (x -> "even")
    case x => (x -> "odd")
 }
 ListMap(tuples:_*)
Run Code Online (Sandbox Code Playgroud)

是的,您也可以从 for-comprehension 中屈服(我不确定在这种情况下您为什么要这样做),如下所示:

val tuples = for {
  x <- 1 to 10 
  kind = if (x %2 == 0) "even" else "odd"
} yield (x -> kind) 
Run Code Online (Sandbox Code Playgroud)

这与map上面的调用做同样的事情。

您也可以从头ListMap开始以避免在最后进行转换:

 ListMap((1 to 10).map(_ -> ""):_*).map { 
   case (k, _) if k%2 == 0 => k -> "even"
   case (k, _) => k -> "odd"
 }
Run Code Online (Sandbox Code Playgroud)

要不就:

 ListMap(
    (1 to 10).map {
       case x if x%2 == 0 => x -> "even"
       case x => x -> "odd"
     }:_*
 )
Run Code Online (Sandbox Code Playgroud)

还有.foldLeft,它可以让您以一种最类似于您当前所拥有的方式编写它,它会逐渐累积地图中的更改而不是最后进行一次转换......不知道您为什么想要不过,这是效率最低的方法:

 (1 to 10).foldLeft(ListMap.empty[Int, String]) { 
    case (x, map) if x%2 == 0 => map.updated(x, "even")
    case (x, map) => map.updated(x, "odd")
 }
Run Code Online (Sandbox Code Playgroud)