如何从java.util.Map转换为斯卡拉地图(How to convert from from

2019-07-29 03:21发布

一个Java API返回一个java.util.Map<java.lang.String,java.lang.Boolean> ; 我想它放入一个Map[String,Boolean]

所以,想象一下,我们有:

var scalaMap : Map[String,Boolean] = Map.empty
val javaMap = new JavaClass().map()   // Returns java.util.Map<java.lang.String,java.lang.Boolean>

你不能这样做Map.empty ++ javaMap ,因为++方法不知道有关Java的地图。 我试过了:

scalaMap = Map.empty ++ new collection.jcl.MapWrapper[String,Boolean] {
    override def underlying = javaMap
}

和:

scalaMap = Map.empty ++ new collection.jcl.MapWrapper[java.lang.String,java.lang.Boolean] {
    override def underlying = javaMap
  }

这些都无法编译,因为仿制药的- java.lang.String是不一样的Scala的字符串。

是否有这样做的一个很好的方式,短手动复制的地图?

编辑:谢谢,所有好的答案,我从所有的人都学到了很多东西。 但是,我在这里通过张贴简单的问题一个比我居然犯了一个错误。 所以,如果你让我,我会概括问题 - 什么是API实际上是返回

java.util.Map<java.lang.String, java.util.Map<SomeJavaEnum,java.lang.String>>

我需要移动这地图[字符串,地图[SomeJavaEnum,字符串]

这可能似乎并不喜欢太复杂的,但它增加了类型擦除额外的水平,我发现这个移动到斯卡拉地图的唯一途径是深复制它(使用一些你以下建议的技术) 。 任何人任何提示? 我定义为我的确切类型的隐式转换类型的解决我的问题,所以至少丑隐藏在它自己的特点,但还是感觉有点笨拙深复制的地段。

Answer 1:

At least with Scala 2.9.2 there's an easier way with the collections conversions: import "import collection.JavaConversions._" and use "toMap".

Example:

// show with Java Map:

scala> import java.util.{Map=>JMap}
scala> val jenv: JMap[String,String] = System.getenv()
jenv: java.util.Map[String,String] = {TERM=xterm, ANT_OPTS=-Xmx512m ...}

scala> jenv.keySet()
res1: java.util.Set[String] = [TERM, ANT_OPTS...]

// Now with Scala Map:

scala> import collection.JavaConversions._
scala> val env: Map[String,String] = System.getenv.toMap // <--- TADA <---
env: Map[String,String] = Map(ANT_OPTS -> -Xmx512m, TERM -> xterm ...)

// Just to prove it's got Scala functionality:

scala> env.filterKeys(_.indexOf("TERM")>=0)
res6: scala.collection.immutable.Map[String,String] = Map(TERM -> xterm, 
  TERM_PROGRAM -> iTerm.app, ITERM_PROFILE -> Default)

It works fine with a java.util.map of String to Boolean.



Answer 2:

Scala的String是一个java.lang.String ,但 Scala的Boolean 是不是 java.lang.Boolean 。 因此,以下工作:

import collection.jcl.Conversions._
import collection.mutable.{Map => MMap}
import java.util.Collections._
import java.util.{Map => JMap}

val jm: JMap[String, java.lang.Boolean] = singletonMap("HELLO", java.lang.Boolean.TRUE)

val sm: MMap[String, java.lang.Boolean] = jm //COMPILES FINE

但你的问题仍然是与问题Boolean差异。 你必须“折叠”在Java映射到一个阶:使用斯卡拉再试一次Boolean类型:

val sm: MMap[String, Boolean] = collection.mutable.Map.empty + ("WORLD" -> false)
val mm = (sm /: jm) { (s, t2) => s + (t2._1 -> t2._2.booleanValue) }

然后mm是包含原始斯卡拉地图的内容以及什么是在Java地图Scala的地图



Answer 3:

Usejvanapkscl

import test._
import java.lang.Boolean
import java.util.{Map => JavaMap}
import collection.jcl.MapWrapper

object useJavaMap {
  def main(args: Array[String]) {
    var scalaMap : Map[String, Boolean] = Map.empty
    scalaMap = toMap(test.testing())
    println(scalaMap)
  }

  def toMap[K, E](m: JavaMap[K, E]): Map[K, E] = {
    Map.empty ++ new MapWrapper[K, E]() {
      def underlying = m
    }
  }
}

测试/ test.java

package test;

import java.util.*;

public class test {
    public static Map<String, Boolean> testing() {
        Map<String, Boolean> x = new HashMap<String, Boolean>();
        x.put("Test",Boolean.FALSE);
        return x;
    }
    private test() {}
}

命令行

javac test\test.java
scalac useJavaMap.scala
scala useJavaMap
> Map(Test -> false)


Answer 4:

我想我有一个部分答案...

如果您在Java地图转换为斯卡拉地图的Java类型。 然后,您可以将其映射到斯卡拉类型的斯卡拉地图:

val javaMap = new java.util.TreeMap[java.lang.String, java.lang.Boolean]
val temp = new collection.jcl.MapWrapper[java.lang.String,java.lang.Boolean] {
    override def underlying = javaMap
}
val scalaMap = temp.map{
    case (k, v) => (k.asInstanceOf[String] -> v.asInstanceOf[Boolean])
}

在这个计划中的缺陷是,类型scalaMap是可迭代[(java.lang.String中,布尔值)]不是地图。 我感觉如此接近,能有人比我聪明修复的最后一条语句,使这项工作?



文章来源: How to convert from from java.util.Map to a Scala Map