【问题标题】:scala map in a method argument can not add key-value方法参数中的scala映射无法添加键值
【发布时间】:2017-03-19 08:05:13
【问题描述】:

在 Scala 中,如何将映射作为引用对象传递给方法,以便我可以向该映射添加键值。我试过这段代码,它不起作用。

var rtnMap = Map[Int, String]()
def getUserInputs(rtnMap: Map[Int, String]) {
   rtnMap += (1-> "ss") //wrong here
}

我知道,默认情况下,方法中的参数是 val,就像 java 中的 final,它可以提供一些安全性。但至少它应该允许我们插入一个新条目。你有什么想法吗?

【问题讨论】:

  • 你真的需要吗?尝试采用不可变集合。

标签: scala


【解决方案1】:

欢迎使用函数式编程

首先,您的用例可以使用mutable map。您使用了immutable map,因为它在 Scala 中默认可用。 scala.Predef 包中的所有内容默认在 Scala 中可用,默认情况下您不需要导入它。

下面的代码作为例外工作。

import scala.collection.mutable.Map

val gMap = Map[Int, String]()

def getUserInputs(lMap: Map[Int, String]) = {
   lMap += (1-> "ss")
}

下面的调用会改变gMap的内容

getUserInputs(gMap)

这是证据

scala> import scala.collection.mutable.Map
import scala.collection.mutable.Map

scala>
     |     val gMap = Map[Int, String]()
gMap: scala.collection.mutable.Map[Int,String] = Map()

scala>
     |     def getUserInputs(lMap: Map[Int, String]) = {
     |        lMap += (1-> "ss")
     |     }
getUserInputs: (lMap: scala.collection.mutable.Map[Int,String])scala.collection.mutable.Map[Int,String]

scala> getUserInputs(gMap)
res2: scala.collection.mutable.Map[Int,String] = Map(1 -> ss)

scala> gMap
res3: scala.collection.mutable.Map[Int,String] = Map(1 -> ss)

在最后一个 Scala repl 中注意 gMap 的内容。 gMap 包含添加的项目。

一般代码改进

除非你有充分的理由使用它,否则不要使用可变集合。

如果是不可变集合,则在完成更改现有数据结构的操作时会返回新实例。这样现有的数据结构不会改变。这在很多方面都很好。这确保了程序的正确性,也确保了所谓的引用透明性(阅读它)。

所以你的程序理想情况下应该是这样的

val gMap = Map.empty[String, String] //Map[String, String]()

def getUserInputs(lMap: Map[Int, String]) = {
       lMap += (1-> "ss")
}

val newMap = getUserInputs(gMap)

内容被添加到newMap 并且旧地图没有改变,保持不变。这非常有用,因为保留gMap 并访问gMap 的代码不必担心底层结构发生的变化。(假设在多线程场景中,它非常有用。)

保持原始结构不变并为更改的状态创建新实例是函数式编程中处理状态的一般方式。所以理解这一点并实践这一点很重要。

Scala 2.12 中已弃用的语法及其删除

你像下面这样声明了你的函数

def getUserInputs(lMap: Map[Int, String]) { // no = here
  lMap += (1-> "ss")
}

在上述函数定义中,右括号后没有=。这在 Scala 2.12 中已被弃用。所以不要使用它,因为 Scala 编译器使用这种函数声明语法会产生误导性的编译错误。

正确的做法是这样。

def getUserInputs(lMap: Map[Int, String]) = { 
 lMap += (1-> "ss")
}

请注意,此语法中有 =

【讨论】:

    【解决方案2】:

    要传递对地图的引用并更改 that 地图,您需要使用 可变 地图实现(Scala 中的默认值是不可变地图,无论是否声明为valvar),因此@Esardes 的答案的替代方案(如果rtnMap 不在定义getUserInputs 的范围内,也可以使用)是:

    import scala.collection.mutable
    
    def getUserInputs(map: mutable.Map[Int, String]) {
      map += (1 -> "ss") // mutating "map"
    }
    
    val rtnMap = mutable.Map[Int, String]() // notice this can be a val
    getUserInputs(rtnMap)
    println(rtnMap)
    // Map(1 -> ss)
    

    【讨论】:

      【解决方案3】:

      您可以将值包装在一个对象中,然后作为参数传递,或者,如果它在您的函数范围内可用,您可以直接编写

      def getUserInputs = {
         rtnMap += (1-> "ss") 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-26
        • 2023-03-15
        • 1970-01-01
        • 2012-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多