使用JavaConversions在java和scala集合之间进行隐式转换

时间:2016-07-12 05:32:22

标签: java scala scala-collections

我使用通用函数合并了scala Set的scala Map

def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] =
(Map[A, B]() /: (for (m <- ms; kv <- m) yield kv))
{
  (a, kv) =>
  a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv)
}

这可以处理存在相同键冲突的情况。但是,我想在Scala Code中使用Java集合。我研究了一下,遇到了JavaConversions。我导入了它并写了这个

def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] =
(new util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv))
{
  case (a, kv) =>
    a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv)
}

然而,它表示存在类型不匹配

Error:(67, 11) type mismatch;
found   : scala.collection.mutable.Map[A,B]
required: java.util.HashMap[A,B]
    a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv)
      ^

JavaConversions用于隐式转换util.HashMapmutable.Map?我在这里缺少什么?

2 个答案:

答案 0 :(得分:5)

JavaConverter会做你想要的吗?

scala> import scala.collection.JavaConverters._
import scala.collection.JavaConverters._

scala> val x = (new java.util.HashMap[Int,Int]).asScala
x: scala.collection.mutable.Map[Int,Int] = Map()

答案 1 :(得分:2)

他们说要尝试JavaConverters,因为JavaConversions已被弃用。

scala> import collection.JavaConverters._
import collection.JavaConverters._

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] =
     | (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) {
     | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
<console>:16: error: value contains is not a member of java.util.HashMap[A,B]
       case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
                                  ^
<console>:16: error: java.util.HashMap[A,B] does not take parameters
       case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
                                                               ^
<console>:16: error: type mismatch;
 found   : (A, B)
 required: String
       case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
                                                                                    ^
<console>:15: error: type mismatch;
 found   : java.util.HashMap[A,B]
 required: Map[A,B]
       (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) {
                                    ^

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] =
     | (new java.util.HashMap[A, B].asScala /: (for (m <- ms; kv <- m) yield kv)) {
     | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
<console>:15: error: type mismatch;
 found   : scala.collection.mutable.Map[A,B]
 required: scala.collection.immutable.Map[A,B]
       (new java.util.HashMap[A, B].asScala /: (for (m <- ms; kv <- m) yield kv)) {
                                            ^

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] =
     | (new java.util.HashMap[A, B].asScala.toMap /: (for (m <- ms; kv <- m) yield kv)) {
     | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
mergeMaps: [A, B](ms: Set[Map[A,B]])(f: (B, B) => B)Map[A,B]

也许是为了说明它被弃用的原因:

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] =
     | (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) {
     | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
<console>:19: error: type mismatch;
 found   : scala.collection.mutable.Map[A,B]
 required: java.util.HashMap[A,B]
       case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
                         ^
<console>:18: error: type mismatch;
 found   : java.util.HashMap[A,B]
 required: Map[A,B]
       (new java.util.HashMap[A, B] /: (for (m <- ms; kv <- m) yield kv)) {
                                    ^

注意到for comprehension产生一组对。

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B) = for (m <- ms; kv <- m) yield kv
mergeMaps: [A, B](ms: Set[Map[A,B]])(f: (B, B) => B)scala.collection.immutable.Set[(A, B)]

显然,推理无法进行转换,然后找出操作类型。

有时打破表达有助于推理,但不是在这里。

scala> def mergeMaps[A, B](ms: Set[Map[A, B]])(f: (B, B) => B): Map[A, B] = {
     | val ss = for (m <- ms; kv <- m) yield kv
     | (new java.util.HashMap[A, B] /: ss) {
     | case (a, kv) => a + (if (a.contains(kv._1)) kv._1 -> f(a(kv._1), kv._2) else kv) }
     | }