Conversión de una colección Java en una colección Scala

88

En relación con la pregunta de Stack Overflow equivalente a Scala del nuevo HashSet (Colección) , ¿cómo convierto una colección de Java (por java.util.Listejemplo) en una colección de Scala List?

De hecho, estoy tratando de convertir una llamada a la API de Java en Spring SimpleJdbcTemplate , que devuelve a java.util.List<T>, en un Scala inmutable HashSet. Así por ejemplo:

val l: java.util.List[String] = javaApi.query( ... )
val s: HashSet[String] = //make a set from l

Esto parece funcionar. ¡Las críticas son bienvenidas!

import scala.collection.immutable.Set
import scala.collection.jcl.Buffer 
val s: scala.collection.Set[String] =
                      Set(Buffer(javaApi.query( ... ) ) : _ *)
oxbow_lakes
fuente

Respuestas:

17

Su última sugerencia funciona, pero también puede evitar usar jcl.Buffer:

Set(javaApi.query(...).toArray: _*)

Tenga en cuenta que scala.collection.immutable.Setestá disponible de forma predeterminada gracias a Predef.scala.

Jorge Ortiz
fuente
9
Esta sugerencia no funciona donde quiero mantener la información de tipo
oxbow_lakes
127

Para referencia futura: Con Scala 2.8, podría hacerse así:

import scala.collection.JavaConversions._
val list = new java.util.ArrayList[String]()
list.add("test")
val set = list.toSet

setes un scala.collection.immutable.Set[String]después de esto.

También vea la respuesta de Ben James para una forma más explícita (usando JavaConverters), que parece recomendarse ahora.

Robinst
fuente
Parece que ahora JavaConversionstiene algunas implicaciones que hacen que la toSetllamada no sea necesaria.
Rajish
@Rajish Creo que es mejor si la conversión es explícita (consulte stackoverflow.com/questions/8301947/… )
krookedking
tienes razón, es mejor usar import scala.collection.JavaConverters._
Abhishek Sengupta
62

Si desea ser más explícito que las JavaConversions demostradas en la respuesta de robinst , puede usar JavaConverters:

import scala.collection.JavaConverters._
val l = new java.util.ArrayList[java.lang.String]
val s = l.asScala.toSet
Ben James
fuente
25

JavaConversions ( respuesta de robinst ) y JavaConverters ( respuesta de Ben James ) han quedado obsoletos con Scala 2.10 .

En lugar de JavaConversions, utilice:

import scala.collection.convert.wrapAll._

como sugiere aleksandr_hramcov .

En lugar de JavaConverters use:

import scala.collection.convert.decorateAll._

Para ambos también existe la posibilidad de importar solo las conversiones / convertidores a Java o Scala respectivamente, por ejemplo:

import scala.collection.convert.wrapAsScala._

Actualización: La declaración anterior de que JavaConversions y JavaConverters estaban en desuso parece ser incorrecta. Hubo algunas propiedades en desuso en Scala 2.10, lo que resultó en advertencias de desuso al importarlas. Entonces, las importaciones alternativas aquí parecen ser solo alias. Aunque todavía los prefiero, en mi humilde opinión, los nombres son más apropiados.

stempler
fuente
¿Por qué dice que JavaConversions y JavaConverters están en desuso? En la documentación actual 2.11.8 ambos no están marcados como obsoletos y tampoco tienen una referencia a 'decorateAll' o 'wrapAll' indicando que es el uso nuevo y preferido.
Joost den Boer
@JoostdenBoer Parece que hubo algunos decoradores obsoletas hay en Scala 2.10, a pesar de que parecen haber sido eliminado de nuevo con Scala 2.11.
stempler
14

Es posible que también desee explorar esta excelente biblioteca: scalaj-collection que tiene conversión bidireccional entre las colecciones de Java y Scala. En su caso, para convertir un java.util.List a Scala List, puede hacer esto:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala
Surya Suravarapu
fuente
1
Esa biblioteca es la cosa más grandiosa que jamás haya existido. Realmente funciona bien.
Michael Neale
7
Revisando esto después de un par de años, JavaConverters de Scala es el camino a seguir.
Surya Suravarapu
5

Comenzando Scala 2.13, el paquete scala.jdk.CollectionConvertersreemplaza a los paquetes scala.collection.JavaConverters/JavaConversions._:

import scala.jdk.CollectionConverters._

// val javaList: java.util.List[String] = java.util.Arrays.asList("one","two","three")
javaList.asScala
// collection.mutable.Buffer[String] = Buffer("one", "two", "three")
javaList.asScala.toSet
// collection.immutable.Set[String] = Set("one", "two", "three")
Xavier Guihot
fuente
3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])
jamesqiu
fuente
esta es una gran respuesta y resolvió mi problema. La mayoría de los métodos mencionados en Internet simplemente convierten (por ejemplo) java.util.List [java.lang.Long] en scala.collection.immutable.List [java.lang.Long]. Así que este método me funcionó para convertirlo a scala.collection.immutable.List [scala.Long]
ajkl
2

Puede agregar la información de tipo en la llamada toArray para hacer que el Set sea parametrizado:

 val s = Set(javaApi.query(....).toArray(new Array[String](0)) : _*)

Esto podría ser preferible ya que el paquete de colecciones está pasando por una revisión importante para Scala 2.8 y el paquete scala.collection.jcl va a desaparecer.

Aaron
fuente
1

Puede convertir la colección de Java en una matriz y luego crear una lista Scala a partir de eso:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)
Fabian Steeg
fuente
2
Esto no es genial porque mi java.util.List está saliendo de una API de Java como una lista parametrizada (por lo que mi llamada a la API produce un java.util.List <String>). Estoy tratando de convertir esto en un HashSet inmutable de scala
oxbow_lakes
1

Otra forma sencilla de solucionar este problema:

import collection.convert.wrapAll._
aleksandr_hramcov
fuente