Was ist der Unterschied zwischen JavaConverters und JavaConversions in Scala?

Antworten:

253

EDIT: Java Conversionsbekam @deprecatedin Scala 2.13.0. Verwenden Sie stattdessen scala.jdk.CollectionConverters .

JavaConversionsStellen Sie eine Reihe impliziter Methoden bereit, die zwischen einer Java-Sammlung und der nächstgelegenen entsprechenden Scala-Sammlung konvertieren und umgekehrt. Dazu werden Wrapper erstellt, die entweder die Scala-Schnittstelle implementieren und die Aufrufe an die zugrunde liegende Java-Sammlung oder die Java-Schnittstelle weiterleiten und die Aufrufe an die zugrunde liegende Scala-Sammlung weiterleiten.

JavaConvertersverwendet das pimp-my-library-Muster, um die asScalaMethode zu den Java-Sammlungen und die asJavaMethode zu den Scala-Sammlungen hinzuzufügen , die die oben beschriebenen entsprechenden Wrapper zurückgeben. Es ist neuer (seit Version 2.8.1) als JavaConversions(seit 2.8) und macht die Konvertierung zwischen Scala und Java-Sammlung explizit. Im Gegensatz zu dem, was David in seiner Antwort schreibt, würde ich empfehlen, dass Sie es sich zur Gewohnheit machen, es zu verwenden, JavaConvertersda Sie mit viel geringerer Wahrscheinlichkeit Code schreiben, der viele implizite Konvertierungen durchführt, da Sie den einzigen Ort steuern können, an dem dies geschehen wird : wo du schreibst .asScalaoder .asJava.

Hier sind die Konvertierungsmethoden, die Folgendes JavaConvertersbieten:

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]

Um die Konvertierungen direkt von Java aus zu verwenden, sollten Sie Methoden besser direkt von Java aus aufrufen JavaConversions. z.B:

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
quelle
5
Ja, verwenden Sie JavaConverters über JavaConversions. Erwägen Sie jedoch auch die Verwendung von github.com/scalaj/scalaj-collection, da dies einige Vorteile für die Konvertierung von java.util.List in Seq bietet. (Ist die obige Liste von 2.8.1?)
Oluies
7
@David Während implizite Konvertierungen wie die von bereit JavaConversionssind, können Sie schnell alle Stellen übersehen, an denen sie vom Compiler eingefügt werden können. Sie kontrollieren diese Orte mitJavaConverters . Es ist die ganze Diskussion über implizite oder explizite Konvertierung.
Jean-Philippe Pellet
1
@ Jean-PhilippePellet implizite Conversions in Scala basieren auf dem Scope. Wenn Sie dies nicht tun import JavaConversions._, werden keine Conversions durchgeführt, sodass Sie die Kontrolle darüber haben, was konvertiert wird. Wenn Sie den Import richtig platzieren (nur bei Bedarf), haben Sie die volle Kontrolle darüber, wo die Konvertierung durchgeführt wird.
David
2
@ David ... und mit JavaConvertersIhnen haben Sie die zusätzliche Sicherheit, dass nichts passiert, wenn Sie es nicht explizit schreiben. Das ist eine zusätzliche Sicherheit, und das ist höchstwahrscheinlich der Grund, warum diese Klasse hinzugefügt wurde.
Jean-Philippe Pellet
23
Sie würden denken, die Benennung wäre besser: Zum Beispiel wäre etwas wie "JavaConversionsImplicit" und "JavaConversionsExplicit" leichter zu unterscheiden gewesen.
Raman
52

Für alle, die seit Scala 2.12.x auf dieser Frage landen, JavaConversionsist sie jetzt veraltet und JavaConvertersdie bevorzugte Methode.

Ryan Burke
quelle
2
Da Scala 2.13 JavaConvertersveraltet ist und scala.jdk.CollectionConvertersdie bevorzugte Methode ist;)
Antonon
4

In Scala 2,13, JavaConverterswurde als veraltet für scala.jdk.CollectionConverters:

... neues Paket scala.jdkmit Objekten CollectionConverters (klassische Java-Sammlungen, ähnlich wie collection.JavaConvertersin 2.12) StreamConverters, FunctionConvertersund OptionConverters...

Mario Galic
quelle
3

Wie in der API erläutert, JavaConversionshandelt es sich um eine Reihe impliziter Konvertierungen, mit denen Java-Sammlungen in verwandte Scala-Sammlungen umgewandelt werden.

Sie können es mit einem verwenden import collection.JavaConversions._. Bei Bedarf wandelt der Compiler die Java-Sammlung automatisch in den richtigen Scala-Typ um.

JavaConvertersist eine Reihe von Dekorateur , die mit Java oder scala Sammlungen zu scala oder Java - Sammlungen helfen verwandeln asScalaoder asJavaMethoden , die implizit in der Sammlung hinzugefügt werden , dass Sie transformieren mögen. Um diese Konverter verwenden zu können, müssen Sie Folgendes importieren:

import collection.JavaConverters._

Sie sollten es vorziehen, JavaConversionsda es im Allgemeinen einfacher zu bedienen ist (keine Notwendigkeit zu verwenden asScalaoder asJava).

David
quelle
15
Während die Verwendung des vollständig impliziten Ansatzes von JavaConverters einfacher zu schreiben ist, ist es schwieriger zu lesen. Der aktuelle Scala-Stil schlägt vor, Methoden zur Durchführung von Konvertierungen explizit aufzurufen, weshalb JavaConverter jetzt bevorzugt werden.
Leif Wickland
JavaConversions sind in Scala 2.12 veraltet
Andrzej Wąsowski am