2009-03-23 55 views
83

En relación con desbordamiento de pila pregunta Scala equivalent of new HashSet(Collection), ¿cómo puedo convertir una colección de Java (java.util.List dicen) en una colección Scala List?la conversión de una colección de Java en una colección Scala

De hecho, estoy tratando de convertir una llamada a la API Java para Spring'sSimpleJdbcTemplate, que devuelve un 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. ¡Crítica es bienvenida!

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

Respuesta

16

Su última sugerencia obras, pero también se puede evitar el uso de jcl.Buffer:

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

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

+9

Esta sugerencia no funciona donde quiero guardar el tipo de información –

1

Se podría convertir la colección de Java a una matriz y luego crear una lista Scala de eso:

val array = java.util.Arrays.asList("one","two","three").toArray 
val list = List.fromArray(array) 
+2

Esto no es genial porque mi java.util.List regresa de una API de Java como una lista parametrizada (por lo que mi llamada a la API produce una java.util.List ) - Estoy tratando de convertir esto en un scala inmutable HashSet –

2

Puede agregar la información de tipo en el toArray llamar para hacer que el conjunto puede parametrizar:

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

Esto podría ser preferible que el paquete de colecciones está pasando por una reanudación importante para Scala 2.8 y el scala.collection El paquete .jcl es going away

14

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

val list = new java.util.ArrayList[java.lang.String] 
list.add("A") 
list.add("B") 
list.asScala 
+1

Esa biblioteca es lo mejor que hay. Realmente realmente funciona bien –

+4

Revisando esto después de un par de años, JavaConverters de Scala es el camino a seguir. –

4
val array = java.util.Arrays.asList("one","two","three").toArray 

val list = array.toList.map(_.asInstanceOf[String]) 
+0

esta es una gran respuesta y resolvió mi problema. La mayoría de los métodos mencionados en Internet simplemente convierten el (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 en scala.collection.immutable.List [scala.Long] – ajkl

120

Para futuras consultas: Con Scala 2.8, se podría hacer así:

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

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

También vea Ben James' answer para una forma más explícita (usando JavaConverters), que parece ser recomendado ahora.

+1

¡Funciona como un amuleto casi todo el tiempo! –

+7

@oxbow_lakes Creo que es hora de marcar esta respuesta como la aceptada. –

+0

Parece que ahora 'JavaConversions' tiene algunas implicaciones que hacen que la llamada' toSet' no sea necesaria. – Rajish

57

Si quieres ser más explícito que los JavaConversions se manifestaron en robinst's answer, se pueden utilizar JavaConverters:

import scala.collection.JavaConverters._ 
val l = new java.util.ArrayList[java.lang.String] 
val s = l.asScala.toSet 
+3

escribiendo en este código literal (sí, incluida la línea de importación) produce lo siguiente en el "error de REPL: valor comoScala no es miembro de java.util.ArrayList [java.lang.String]" – robbbbbb

+1

Vaya, me perdí el comodín '._' de la importación. Fijo. –

2

Otra manera simple de resolver este problema:

import collection.convert.wrapAll._ 
25

JavaConversions (robinst's answer) y JavaConverters (Ben James's answer) han quedado en desuso con Scala 2.10.

En lugar de JavaConversions uso:

import scala.collection.convert.wrapAll._ 

según lo sugerido por aleksandr_hramcov.

En lugar de JavaConverters uso:

import scala.collection.convert.decorateAll._ 

Por tanto también existe la posibilidad de importación exclusivamente las conversiones/convertidores a Java o Scala, respectivamente, por ejemplo:

import scala.collection.convert.wrapAsScala._ 

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

+0

¿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. –

+0

@JoostdenBoer Parece que hubo algunos decoradores obsoletos [allí] (https://github.com/scala/scala/blob/2.10.x/src/library/scala/collection/JavaConverters.scala) en Scala 2.10, aunque parecen haber sido eliminado nuevamente con Scala 2.11. – stempler

Cuestiones relacionadas