Jaka jest różnica między JavaConverters a JavaConversions w Scali?

Odpowiedzi:

253

EDYCJA: Java Conversionsdostałem się @deprecateddo Scali 2.13.0. Zamiast tego użyj scala.jdk.CollectionConverters .

JavaConversionsudostępnia szereg niejawnych metod, które konwertują między kolekcją Java a najbliższą odpowiednią kolekcją Scala i odwrotnie. Odbywa się to poprzez tworzenie opakowań, które implementują interfejs Scala i przekazują wywołania do podstawowej kolekcji Java lub interfejs Java, przekazując wywołania do podstawowej kolekcji Scala.

JavaConvertersużywa wzorca pimp-my-library, aby „dodać” asScalametodę do kolekcji Java i asJavametodę do kolekcji Scala, które zwracają odpowiednie opakowania omówione powyżej. Jest nowszy (od wersji 2.8.1) niż JavaConversions(od 2.8) i wyraźnie określa konwersję między Scalą a kolekcją Java. W przeciwieństwie do tego, co pisze David w swojej odpowiedzi, zalecam, abyś przyzwyczaił się go używać, JavaConvertersponieważ znacznie rzadziej będziesz pisać kod, który dokonuje wielu niejawnych konwersji, ponieważ możesz kontrolować jedyne miejsce, w którym to się stanie. : gdzie piszesz .asScalalub .asJava.

Oto metody konwersji, które JavaConverterszapewniają:

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]

Aby korzystać z konwersji bezpośrednio z Javy, lepiej jest wywoływać metody JavaConversionsbezpośrednio; na przykład:

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
źródło
5
Tak, używaj JavaConverters zamiast JavaConversions ,. Zastanów się także nad użyciem github.com/scalaj/scalaj-collection, ponieważ ma on pewne zalety, jak konwersja java.util.List do Seq. (Czy powyższa lista pochodzi z 2.8.1?)
oluies 28.11.11
7
@David Chociaż niejawne konwersje, takie jak te dostarczane przez, JavaConversionssą wygodne, możesz szybko przeoczyć wszystkie miejsca, w których kompilator może je wstawić. Kontrolujesz te miejsca za pomocą JavaConverters. To cała dyskusja na temat konwersji domyślnej vs. jawnej.
Jean-Philippe Pellet
1
@ Niejawne konwersje Jean-PhilippePellet w Scali są oparte na zakresie, więc jeśli nie import JavaConversions._, konwersje nie wystąpią, więc masz kontrolę nad tym, co jest konwertowane. Jeśli umieścisz import w odpowiedni sposób (tylko w razie potrzeby), masz pełną kontrolę nad tym, gdzie konwersja jest wykonywana.
David
2
@David… a przy JavaConverterssobie masz dodatkowe bezpieczeństwo, że nic się nie dzieje, chyba że napiszesz to wprost. To dodatkowe zabezpieczenie i prawdopodobnie dlatego dodano tę klasę.
Jean-Philippe Pellet
23
Można by pomyśleć, że nazewnictwo byłoby lepsze: np. Coś takiego jak „JavaConversionsImplicit” i „JavaConversionsExplicit” byłoby łatwiejsze do odróżnienia.
Raman
52

Dla każdego, kto wyląduje na tym pytaniu od wersji 2.12.x Scala, JavaConversionsjest on obecnie nieaktualny i JavaConvertersjest preferowaną metodą.

Ryan Burke
źródło
2
Ponieważ Scala 2.13 JavaConvertersjest przestarzała i scala.jdk.CollectionConvertersjest preferowaną metodą;)
antonon
4

W Scali 2.13 JavaConverterszostały wycofane na korzyść scala.jdk.CollectionConverters:

... nowy pakiet scala.jdkz obiektami CollectionConverters (klasycznych kolekcjach Java, podobnie jak collection.JavaConvertersw 2.12) StreamConverters, FunctionConvertersa OptionConverters...

Mario Galic
źródło
3

Jak wyjaśniono w interfejsie API, JavaConversionsjest to zestaw niejawnych konwersji, które przekształcają kolekcje Java w pokrewne kolekcje Scala.

Możesz go używać z import collection.JavaConversions._. W razie potrzeby kompilator automatycznie przekształci kolekcję Java w odpowiedni typ Scala.

JavaConvertersto zestaw dekoratora, który pomaga przekształcać zbiory Java lub Scala Scala lub Java z wykorzystaniem zbiorów asScalalub asJavametod, które będą domyślnie dodawane do kolekcji, które chcesz przekształcić. Aby korzystać z tych konwerterów, musisz zaimportować:

import collection.JavaConverters._

Powinieneś preferować, JavaConversionsponieważ generalnie jest łatwiejszy w użyciu (nie musisz używać asScalalub asJava).

David
źródło
15
Podczas gdy korzystanie z całkowicie niejawnego podejścia JavaConverters jest łatwiejsze do napisania, trudniejsze do odczytania. Obecny styl Scala sugeruje, że lepiej jest jawnie wywoływać metody do wykonywania konwersji, dlatego właśnie preferowane są teraz JavaConverters.
Leif Wickland,
JavaConversions są przestarzałe w Scali 2.12
Andrzej Wąsowski,