¿Cuál es la diferencia entre JavaConverters y JavaConversions en Scala?

Respuestas:

253

EDITAR: Java Conversionsconsiguió @deprecateden Scala 2.13.0. Utilice scala.jdk.CollectionConverters en su lugar.

JavaConversionsProporcionar una serie de métodos implícitos que convierten entre una colección Java y la colección Scala correspondiente más cercana, y viceversa. Esto se realiza creando envoltorios que implementan la interfaz Scala y reenvían las llamadas a la colección Java subyacente, o la interfaz Java, reenvían las llamadas a la colección Scala subyacente.

JavaConvertersutiliza el patrón pimp-my-library para "agregar" el asScalamétodo a las colecciones de Java y el asJavamétodo a las colecciones de Scala, que devuelven los contenedores apropiados que se discutieron anteriormente. Es más reciente (desde la versión 2.8.1) que JavaConversions(desde la 2.8) y hace explícita la conversión entre Scala y la colección Java. Contrariamente a lo que David escribe en su respuesta, le recomiendo que se acostumbre a usarlo, JavaConvertersya que será mucho menos probable que escriba código que realice muchas conversiones implícitas, ya que puede controlar el único lugar donde eso sucederá : donde escribes .asScalao .asJava.

Aquí están los métodos de conversión que JavaConvertersproporcionan:

Pimped Type                            | Conversion Method   | Returned Type
=================================================================================================
scala.collection.Iterator              | asJava              | java.util.Iterator
scala.collection.Iterator              | asJavaEnumeration   | java.util.Enumeration
scala.collection.Iterable              | asJava              | java.lang.Iterable
scala.collection.Iterable              | asJavaCollection    | java.util.Collection
scala.collection.mutable.Buffer        | asJava              | java.util.List
scala.collection.mutable.Seq           | asJava              | java.util.List
scala.collection.Seq                   | asJava              | java.util.List
scala.collection.mutable.Set           | asJava              | java.util.Set
scala.collection.Set                   | asJava              | java.util.Set
scala.collection.mutable.Map           | asJava              | java.util.Map
scala.collection.Map                   | asJava              | java.util.Map
scala.collection.mutable.Map           | asJavaDictionary    | java.util.Dictionary
scala.collection.mutable.ConcurrentMap | asJavaConcurrentMap | java.util.concurrent.ConcurrentMap
—————————————————————————————————————————————————————————————————————————————————————————————————
java.util.Iterator                     | asScala             | scala.collection.Iterator
java.util.Enumeration                  | asScala             | scala.collection.Iterator
java.lang.Iterable                     | asScala             | scala.collection.Iterable
java.util.Collection                   | asScala             | scala.collection.Iterable
java.util.List                         | asScala             | scala.collection.mutable.Buffer
java.util.Set                          | asScala             | scala.collection.mutable.Set
java.util.Map                          | asScala             | scala.collection.mutable.Map
java.util.concurrent.ConcurrentMap     | asScala             | scala.collection.mutable.ConcurrentMap
java.util.Dictionary                   | asScala             | scala.collection.mutable.Map
java.util.Properties                   | asScala             | scala.collection.mutable.Map[String, String]

Sin embargo, para usar las conversiones directamente desde Java, es mejor llamar a los métodos JavaConversionsdirectamente; p.ej:

List<String> javaList = new ArrayList<String>(Arrays.asList("a", "b", "c"));
System.out.println(javaList); // [a, b, c]
Buffer<String> scalaBuffer = JavaConversions.asScalaBuffer(javaList);
System.out.println(scalaBuffer); // Buffer(a, b, c)
List<String> javaListAgain = JavaConversions.bufferAsJavaList(scalaBuffer);
System.out.println(javaList == javaListAgain); // true
Jean-Philippe Pellet
fuente
55
Sí, use JavaConverters sobre JavaConversions. Pero también considere usar github.com/scalaj/scalaj-collection ya que tiene algunos beneficios como convertir java.util.List a Seq. (¿Es la lista anterior de 2.8.1?)
oluies
77
@David Si bien las conversiones implícitas, como las proporcionadas por, JavaConversionsson convenientes, puede pasar por alto rápidamente todos los lugares donde el compilador puede insertarlas. Tú controlas esos lugares con JavaConverters. Es toda la discusión sobre la conversión implícita vs explícita.
Jean-Philippe Pellet
1
@ Jean-PhilippePellet las conversiones implícitas en Scala se basan en el alcance, por lo que si no lo hace import JavaConversions._, las conversiones no ocurrirán, por lo que tendrá el control sobre lo que se convierte. Si realiza la importación de la manera correcta (solo cuando sea necesario), tiene control total sobre dónde se realiza la conversión.
David
2
@David ... y con JavaConvertersusted tiene la seguridad adicional de que no pasa nada a menos que lo escriba explícitamente. Esa es una seguridad adicional, y probablemente es por eso que se agregó esta clase.
Jean-Philippe Pellet
23
Se podría pensar que la denominación sería mejor: por ejemplo, algo como "JavaConversionsImplicit" y "JavaConversionsExplicit" habría sido más fácil de distinguir.
Raman
52

Para cualquiera que llegue a esta pregunta desde Scala 2.12.x, JavaConversionsahora está en desuso y JavaConverterses el método preferido.

Ryan Burke
fuente
2
Desde Scala 2.13, JavaConvertersestá en desuso y scala.jdk.CollectionConverterses el método preferido;)
antonone
4

En Scala 2.13, JavaConvertershan quedado en desuso a favor de scala.jdk.CollectionConverters:

... nuevo paquete scala.jdkcon objetos CollectionConverters (colecciones clásicas de Java, similares a las collection.JavaConvertersde 2.12) StreamConverters, FunctionConvertersy OptionConverters...

Mario Galic
fuente
3

Como se explica en la API, JavaConversionses un conjunto de conversiones implícitas que transforma las colecciones java en colecciones scala relacionadas.

Puedes usarlo con un import collection.JavaConversions._. Cuando sea necesario, el compilador transformará automáticamente la colección java en el tipo de escala correcto.

JavaConvertersson un conjunto de decorador que ayuda a transformar las colecciones de Java o scala scala a las colecciones o Java utilizando asScalao asJavamétodos que serán añadidos de forma implícita a la colección que desea transformar. Para utilizar estos convertidores, debe importar:

import collection.JavaConverters._

Usted debe preferir JavaConversions, ya que es generalmente más fácil de usar (sin necesidad de utilizar asScalao asJava).

David
fuente
15
Si bien el uso del enfoque totalmente implícito de JavaConverters es más fácil de escribir, es más difícil de leer. El estilo actual de Scala sugiere que es mejor llamar explícitamente a los métodos para realizar conversiones, por lo que ahora se prefieren JavaConverters.
Leif Wickland
Las conversiones de Java están en desuso en Scala 2.12
Andrzej Wąsowski el