考虑一个类,如下所示:

import scala.collection.mutable.{HashMap => MutableHashMap}
class CustomHashMap[K,V](hashMap: MutableHashMap[K,V], initVal: V) {
  def addMaps(first: MutableHashMap[K, V], second: MutableHashMap[K, V]): MutableHashMap[K, V] = {
    second.foreach(pair => { first += (pair._1 -> (first.getOrElse(pair._1, initVal) + pair._2)) } )
    //The above line throws a compile time error
    first
  }
  //Other functions
}

添加两个参数化类型后,会出现编译时错误
expected (K,V) recieved (K,String)

我想知道为什么scala会做这种隐式转换?由于java中不允许运算符重载,这似乎合乎逻辑,但在scala的情况下,V实际上可能是一个可以为其定义方法+的类。

最佳答案

这是一种如何手动实现这种事情的方法:

由于看起来您正在尝试定义一个幺半群,我将冒昧地将 initValaddMaps 移动到操作的定义中。

这可以通过 Scala 中的通用类型类模式来完成,但您必须手动定义 + 对每种类型的含义,您想在 map 中使用。

基本上你有一个特征 Monoid :

trait Monoid[T] {
  def mzero: T                        // your initVal
  def madd(first: T, second: T): T    // the + operation
}

比您为扩展该特征的每种类型定义隐式实现。您可以在
  • Monoid 的伴生对象,会自动使用,
  • 类 T 的伴生对象,也会自动使用,
  • 作为隐式其他地方,但您必须手动导入它。

  • 下面是一个 Monoid 伴随对象的例子,它定义了字符串和各种数字的实现:
    object Monoid {
      implicit object StringMonoid extends Monoid[String] {
        def mzero = ""
        def madd(first: String, second: String) = first + second
      }
    
      implicit def NumericMonoid[T](implicit ev: Numeric[T]): Monoid[T] =
        new Monoid[T] {
          import Numeric.Implicits._
    
          def mzero = ev.zero
          def madd(first: T, second: T) = first + second
        }
    }
    

    然后在您的 addMaps 函数请求映射的元素应该是 Monoid s,并使用由 monoid 实现对元素提供的操作:
    def addMaps[K, V](first: MutableHashMap[K, V], second: MutableHashMap[K, V])
                     (implicit ev: Monoid[V]): MutableHashMap[K, V] = {
      second.foreach { pair =>
        first += (pair._1 -> ev.madd(first.getOrElse(pair._1, ev.mzero), pair._2)) }
      first
    }
    

    这是一个测试它是如何工作的:
    scala> addMaps(MutableHashMap(1 -> 2, 3 -> 4), MutableHashMap(1 -> 3, 5 -> 7))
    res1: scala.collection.mutable.HashMap[Int,Int] = Map(5 -> 7, 1 -> 5, 3 -> 4)
    
    scala> addMaps(MutableHashMap(1 -> "foo", 2 -> "bar"), MutableHashMap(1 -> "baz", 3 -> "qoo"))
    res2: scala.collection.mutable.HashMap[Int,String] = Map(2 -> bar, 1 -> foobaz, 3 -> qoo)
    

    关于java - 为什么scala中参数化类型的+运算符总是导致字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30820261/

    10-10 10:58
    查看更多