【问题标题】:How to convert a nested scala collection to a nested Java collection如何将嵌套的 Scala 集合转换为嵌套的 Java 集合
【发布时间】:2012-12-08 13:15:21
【问题描述】:

我在 Scala 和 Java 之间遇到了编译问题。

我的 Java 代码需要一个

java.util.Map<Double, java.lang.Iterable<Foo>>

我的 scala 代码有一个

Map[Double, Vector[Foo]]

我得到编译错误:

error: type mismatch;
found   : scala.collection.immutable.Map[scala.Double,Vector[Foo]
required: java.util.Map[java.lang.Double,java.lang.Iterable[Foo]]

似乎 scala.collection.JavaConversions 不适用于嵌套集合,即使 Vector 可以隐式转换为 Iterable。没有遍历 scala 集合并手动进行转换,我可以做些什么来使类型工作吗?

【问题讨论】:

    标签: java scala generics scala-collections


    【解决方案1】:

    scala.collection.JavaConversions 恕我直言,应该弃用。您最好使用scala.collection.JavaConverters 明确说明转换发生的地点和时间。在你的情况下:

    import scala.collection.JavaConverters._
    
    type Foo = Int // Just to make it compile
    val scalaMap = Map(1.0 -> Vector(1, 2)) // As an example
    
    val javaMap = scalaMap.map { 
      case (d, v) => d -> v.toIterable.asJava
    }.asJava
    

    【讨论】:

    • 感谢您将我指向 JavaConversions。我不知道那些。我还需要为我的方法做一些讨厌的 Java 泛型通配符以使返回类型正常工作,即将我声明的返回类型转换为 public > Map createMap()
    【解决方案2】:

    这更适合我的需要:

      def toJava(m: Any): Any = {
        import java.util
        import scala.collection.JavaConverters._
        m match {
          case sm: Map[_, _] => sm.map(kv => (kv._1, toJava(kv._2))).asJava
          case sl: Iterable[_] => new util.ArrayList(sl.map( toJava ).asJava.asInstanceOf[util.Collection[_]])
          case _ => m
        }
      }
    

    【讨论】:

      【解决方案3】:

      我编写了这个通用函数,它非常适合我的需要。

      def toJava(x: Any): Any = {
        import scala.collection.JavaConverters._
        x match {
          case y: scala.collection.MapLike[_, _, _] => 
            y.map { case (d, v) => toJava(d) -> toJava(v) } asJava
          case y: scala.collection.SetLike[_,_] => 
            y map { item: Any => toJava(item) } asJava
          case y: Iterable[_] => 
            y.map { item: Any => toJava(item) } asJava
          case y: Iterator[_] => 
            toJava(y.toIterable)
          case _ => 
            x
        }
      }
      

      【讨论】:

      • 不错!我也想知道你是否写了一个类似的递归 toScala 函数..
      • ''' 我最终编写的递归 toScala 函数: def toScala(x: Any): Any = { import collection.JavaConversions._ x match { case y: java.util.Map[, _] => mapAsScalaMap(y).map{ case (d, v) => toScala(d) -> toScala(v) } case y: java.lang.Iterable[] => iterableAsScalaIterable (y).toList.map { item: Any => toScala(item) } case y: java.util.Iterator[_] => toScala(y) case _ => x } } '''
      • 另外,我在这里发布了一个相关问题:stackoverflow.com/questions/43462034/…
      【解决方案4】:

      如果有人在 spark-scala 中寻找解决方案,试试这个,

      导入 org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema

      在这里, y 是嵌套的 WrapperArray

      y match {
                case x : WrappedArray[x] =>
                   (x.map(f => f match {case z: GenericRowWithSchema => z.mkString(",").toString()
                                                      case z:Any => z  })).asJavaCollection
                case _ => row.get(i).asInstanceOf[Object]
              }
      

      上面的代码做了两件事, 1) 如果 wrapper Array 具有原始数据类型,则条件 case_ 通过 2) 如果 wrapper Array 具有 Complex 数据类型(比如 struts),则执行 GenericRowWithSchema 案例。

      【讨论】:

        【解决方案5】:

        所有其他解决方案都是 AnyAny,这对于像 Scala 这样的强类型语言来说非常糟糕。
        这是一个尽可能保留类型的解决方案:

        trait AsJava[T, R] {
          def apply(o: T): R
        }
        
        object AsJava extends LowPriorityAsJava {
          implicit class RecursiveConverter[T](o: T) {
            def asJavaRecursive[R](implicit asJava: AsJava[T, R]): R = asJava(o)
          }
        
          implicit lazy val longAsJava: AsJava[Long, lang.Long] = new AsJava[Long, lang.Long] {
            def apply(o: Long): lang.Long = Long.box(o)
          }
        
          implicit lazy val intAsJava: AsJava[Int, lang.Integer] = new AsJava[Int, lang.Integer] {
            def apply(o: Int): lang.Integer = Int.box(o)
          }
        
          implicit lazy val doubleAsJava: AsJava[Double, lang.Double] = new AsJava[Double, lang.Double] {
            def apply(o: Double): lang.Double = Double.box(o)
          }
        
          implicit def mapAsJava[K, V, KR, VR](
              implicit
              keyAsJava: AsJava[K, KR],
              valueAsJava: AsJava[V, VR]
          ): AsJava[Map[K, V], util.Map[KR, VR]] =
            new AsJava[Map[K, V], util.Map[KR, VR]] {
              def apply(map: Map[K, V]): util.Map[KR, VR] =
                map.map { case (k, v) => (keyAsJava(k), valueAsJava(v)) }.asJava
            }
        
          implicit def seqAsJava[V, VR](implicit valueAsJava: AsJava[V, VR]): AsJava[Seq[V], util.List[VR]] =
            new AsJava[Seq[V], util.List[VR]] {
              def apply(seq: Seq[V]): util.List[VR] = seq.map(valueAsJava(_)).asJava
            }
        
          implicit def setAsJava[V, VR](implicit valueAsJava: AsJava[V, VR]): AsJava[Set[V], util.Set[VR]] =
            new AsJava[Set[V], util.Set[VR]] {
              def apply(set: Set[V]): util.Set[VR] = set.map(valueAsJava(_)).asJava
            }
        
          implicit lazy val anyAsJava: AsJava[Any, AnyRef] = new AsJava[Any, AnyRef] {
            def apply(o: Any): AnyRef = o match {
              case x: Map[Any, Any] => mapAsJava(anyAsJava, anyAsJava)(x)
              case x: Seq[Any]      => seqAsJava(anyAsJava)(x)
              case x: Set[Any]      => setAsJava(anyAsJava)(x)
              case x: Long          => longAsJava(x)
              case x: Int           => intAsJava(x)
              case x: Double        => doubleAsJava(x)
              case x                => x.asInstanceOf[AnyRef]
            }
          }
        }
        
        trait LowPriorityAsJava {
          implicit def otherAsJava[T]: AsJava[T, T] = new AsJava[T, T] {
            def apply(o: T): T = o
          }
        }
        

        用法:

        Seq(Seq.empty[Int]).asJavaRecursive
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-10-30
          • 2020-08-24
          • 1970-01-01
          • 2021-08-27
          • 1970-01-01
          • 2010-10-15
          • 1970-01-01
          相关资源
          最近更新 更多