将嵌套的Scala类型转换为Java类型

时间:2015-12-23 13:35:06

标签: java scala

我目前正在处理需要Java类型的AWS Java SDK。

我一直在使用JavaConverters将地图和列表等类型显式转换为java。我一直在遇到越来越复杂的类型,并发现自己不得不深入查看变得笨拙的列表。

我当前的问题是我有一个Map[String, List[String]]将整个对象转换为java很简单,但是当匹配地图中的列表时,我会被类型擦除命中。

val t = m.map{
    case (k, v: List[String]) => k -> v //type erasure so unreachable
}

我在Scala中找到了一个很好的解释Type Tags,这是我想要实现的优雅解决方案。 Scala: What is a TypeTag and how do I use it?

我只是不确定我是如何在模式匹配中实现这一点的。

我实现了一个看起来像这样的方法

def isNestedMap[A : TypeTag](xs: A): Boolean = typeOf[A] match {
    case t if t =:= typeOf[Map[String, List[String]]] => true
    case t => false
}

新案例case (k, v) if isNestedMap(v) => k -> "beans"但是这总是返回false,因为我的方法将类型视为Any

任何想法如何超越这个?或者更好的方法是将深度列表或映射递归转换为它们的java等价物?

谢谢大家。

编辑:Map实际上是Map[String, Any]的一种类型,所以在将其转换为Java之前我需要知道Any的类型

3 个答案:

答案 0 :(得分:2)

我认为你的问题与擦除无关,甚至不需要使用类型标签。以下是关于REPL的快速会话,演示了一种进行转换的方法:

{{1}}

答案 1 :(得分:1)

  

编辑:Map实际上是一种Map [String,Any],所以在将其转换为Java之前我需要知道Any的类型

编译器根据静态类型插入

TypeTag,因此当您调用isNestedMap(v)时,它会看到v: Any并插入isNestedMap[Any](v)(typeTag[Any])

  

或者更好的方法是递归地将深层列表或地图转换为它们的java等价物?

这样的东西
def deepAsJava(x: Any): Any = x match {
  case l: List[_] => l.map(deepAsJava).asJava
  case m: Map[_, _] => m.map { case (k, v) => (k, deepAsJava(v)) }.asJava
  case ... // other collections you want to support
  case x => x
}

您可以将其拆分为listDeepAsJava等单独的函数,以便为每个函数获取更好的类型签名:

def deepAsJava(x: Any): Any = x match {
  case l: List[_] => listDeepAsJava(l)
  case m: Map[_, _] => mapDeepAsJava(m)
  case ... // other collections you want to support
  case x => x
}

def listDeepAsJava(x: List[Any]): java.util.List[Any] = l.map(deepAsJava).asJava
...

答案 2 :(得分:0)

尝试使用Array代替List

val m = Map[String, Array[String]]()
val t = m.map{
    case (k, v: Array[String]) => k -> v //no type erasure
}