utilizan tipos son que principales por para ofrecidas objetos objeto llenar las ejemplo describa conjuntos collection colecciones clases almacenamiento java scala generics scala-collections

tipos - Cómo convertir una colección scala anidada en una colección Java anidada



que son las colecciones de java (5)

Escribí esta función de propósito general, que funciona bien para mis necesidades.

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 } }

Tengo problemas de compilación entre Scala y Java.

Mi código de Java necesita un

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

Mi código de Scala tiene una

Map[Double, Vector[Foo]]

Me sale el error de compilación:

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

Parece que scala.collection.JavaConversions no se aplica a colecciones anidadas, a pesar de que un Vector se puede convertir implícitamente en un Iterable. Aparte de recorrer la colección de scala y hacer la conversión a mano, ¿hay algo que pueda hacer para que los tipos funcionen?


Esto se adapta mejor a mis necesidades:

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 } }


Prueba esto si alguien busca solución en spark-scala,

importar org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema

Aquí, y está anidado 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] }

El código anterior hace dos cosas: 1) Si la matriz de envoltura tiene un tipo de datos primitivo, la condición case_ obtiene 2) Si la matriz de wrapper tiene un tipo de datos complejo (por ejemplo, struts), se ejecuta el caso GenericRowWithSchema.


Todas las otras soluciones son Any to Any , que es bastante mala para un lenguaje fuertemente tipado como Scala.
Aquí hay una solución que mantiene los tipos tanto como sea posible:

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 } }

Uso:

Seq(Seq.empty[Int]).asJavaRecursive


scala.collection.JavaConversions debe estar en desuso IMHO. Es mejor que sea explícito sobre dónde y cuándo ocurre la conversión utilizando scala.collection.JavaConverters . En tu caso:

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