Qual é a diferença entre JavaConverters e JavaConversions no Scala?

Respostas:

253

EDIT: Java Conversionsficou @deprecatedem Scala 2.13.0. Use scala.jdk.CollectionConverters .

JavaConversionsforneça uma série de métodos implícitos que são convertidos entre uma coleção Java e a coleção Scala correspondente mais próxima e vice-versa. Isso é feito criando wrappers que implementam a interface Scala e encaminham as chamadas para a coleção Java subjacente ou a interface Java, encaminhando as chamadas para a coleção Scala subjacente.

JavaConvertersusa o padrão pimp-my-library para "adicionar" o asScalamétodo às coleções Java e o asJavamétodo às coleções Scala, que retornam os wrappers apropriados discutidos acima. É mais recente (desde a versão 2.8.1) que JavaConversions(desde 2.8) e torna explícita a conversão entre a coleção Scala e Java. Ao contrário do que David escreve em sua resposta, eu recomendo que você crie o hábito de usar, JavaConverterspois será muito menos provável que você escreva código que produz muitas conversões implícitas, pois você pode controlar o único ponto em que isso acontecerá : onde você escreve .asScalaou .asJava.

Aqui estão os métodos de conversão que JavaConvertersfornecem:

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]

Para usar as conversões diretamente do Java, é melhor chamar métodos JavaConversionsdiretamente; por exemplo:

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
fonte
5
Sim, use JavaConverters sobre JavaConversions. Mas também considere usar github.com/scalaj/scalaj-collection , pois possui alguns benefícios como converter java.util.List em Seq. (É a lista acima de 2.8.1?)
oluies
7
@ David Embora as conversões implícitas, como as fornecidas por, JavaConversionssejam convenientes, você pode rapidamente ignorar todos os lugares onde elas podem ser inseridas pelo compilador. Você controla esses lugares com JavaConverters. É toda a discussão sobre conversão implícita vs explícita.
Jean-Philippe Pellet
1
As conversões implícitas do Jean-PhilippePellet no Scala são baseadas no escopo; portanto, se não o fizer import JavaConversions._, as conversões não ocorrerão e você terá o controle sobre o que é convertido. Se você colocar a importação da maneira certa (somente quando necessário), terá controle total sobre onde a conversão é feita.
David
2
@ David… e com JavaConvertersvocê tem a segurança adicional de que nada acontece, a menos que você o escreva explicitamente. Essa é uma segurança adicional, e é provavelmente por isso que essa classe foi adicionada.
Jean-Philippe Pellet
23
Você pensaria que a nomeação seria melhor: por exemplo, algo como "JavaConversionsImplicit" e "JavaConversionsExplicit" teria sido mais fácil distinguir.
Raman
52

Para qualquer pessoa que entre nesta questão desde o Scala 2.12.x, JavaConversionsagora está obsoleto e JavaConvertersé o método preferido.

Ryan Burke
fonte
2
Desde Scala 2.13, JavaConvertersfoi preterido e scala.jdk.CollectionConvertersé o método preferido;)
antonone 16/02
4

No Scala 2.13, JavaConvertersforam preteridos em favor de scala.jdk.CollectionConverters:

... novo pacote scala.jdkcom objetos CollectionConverters (coleções Java clássicas, semelhantes às collection.JavaConvertersda versão 2.12) StreamConverters, FunctionConverterse OptionConverters...

Mario Galic
fonte
3

Conforme explicado na API, JavaConversionsé um conjunto de conversões implícitas que transforma coleções de java em coleções de scala relacionadas.

Você pode usá-lo com um import collection.JavaConversions._. Quando necessário, o compilador transformará automaticamente a coleção java no tipo de scala correto.

JavaConverterssão um conjunto de decorador que ajuda a transformar coleções Java ou Scala Scala ou Java coleções usando asScalaou asJavamétodos que serão adicionados implicitamente para a coleção que você deseja transformar. Para usar esses conversores, você precisa importar:

import collection.JavaConverters._

Você deve preferir JavaConversions, pois geralmente é mais fácil de usar (sem necessidade de usar asScalaou asJava).

David
fonte
15
Embora o uso da abordagem totalmente implícita do JavaConverters seja mais fácil de escrever, é mais difícil de ler. O estilo atual do Scala sugere que é melhor chamar explicitamente métodos para realizar conversões, e é por isso que os JavaConverters agora são os preferidos.
Leif Wickland
O JavaConversions está obsoleto no Scala 2.12
Andrzej Wąsowski