Konvertieren einer Java-Sammlung in eine Scala-Sammlung

87

Bezogen auf Stack - Überlauf Frage Scala Äquivalent neuen HashSet (Collection) , wie konvertiere ich eine Java - Sammlung ( java.util.Listsagen wir) in eine Scala Sammlung List?

Ich versuche tatsächlich, einen Java-API-Aufruf in Spring's SimpleJdbcTemplate , der a zurückgibt java.util.List<T>, in eine unveränderliche Scala umzuwandeln HashSet. Also zum Beispiel:

val l: java.util.List[String] = javaApi.query( ... )
val s: HashSet[String] = //make a set from l

Das scheint zu funktionieren. Kritik ist willkommen!

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

Antworten:

17

Ihr letzter Vorschlag funktioniert, aber Sie können auch vermeiden, Folgendes zu verwenden jcl.Buffer:

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

Beachten Sie, dass dies scala.collection.immutable.Setdank standardmäßig verfügbar ist Predef.scala.

Jorge Ortiz
quelle
9
Dieser Vorschlag funktioniert nicht, wenn ich die
Typinformationen
126

Zum späteren Nachschlagen: Mit Scala 2.8 könnte dies folgendermaßen geschehen:

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

setist ein scala.collection.immutable.Set[String]danach.

Siehe auch die Antwort von Ben James für einen expliziteren Weg (mit JavaConverters), der jetzt empfohlen zu werden scheint.

robinst
quelle
7
@oxbow_lakes Ich denke, es ist Zeit, diese Antwort als die akzeptierte zu markieren.
Nikita Volkov
Sieht so aus, als hätte es jetzt JavaConversionseinige Implikationen, die den toSetAnruf nicht notwendig machen.
Rajish
@ Rajish Ich denke, es ist besser, wenn die Konvertierung explizit ist (siehe stackoverflow.com/questions/8301947/… )
krookedking
Sie haben Recht, es ist besser, import scala.collection.JavaConverters._
Abhishek Sengupta
62

Wenn Sie expliziter sein möchten als die in der Antwort von robinst gezeigten JavaConversions , können Sie JavaConverters verwenden:

import scala.collection.JavaConverters._
val l = new java.util.ArrayList[java.lang.String]
val s = l.asScala.toSet
Ben James
quelle
25

JavaConversions ( Antwort von robinst ) und JavaConverters ( Antwort von Ben James ) sind mit Scala 2.10 veraltet .

Verwenden Sie anstelle von JavaConversions :

import scala.collection.convert.wrapAll._

wie von aleksandr_hramcov vorgeschlagen .

Verwenden Sie anstelle von JavaConverters :

import scala.collection.convert.decorateAll._

Für beide gibt es auch die Möglichkeit, nur die Konvertierungen / Konverter nach Java bzw. Scala zu importieren, zB:

import scala.collection.convert.wrapAsScala._

Update: Die obige Aussage, dass JavaConversions und JavaConverters veraltet waren, scheint falsch zu sein. In Scala 2.10 gab es einige veraltete Eigenschaften, die beim Import zu veralteten Warnungen führten. Die alternativen Importe hier scheinen also nur Aliase zu sein. Obwohl ich sie immer noch bevorzuge, sind die Namen meiner Meinung nach angemessener.

stempler
quelle
Warum sind JavaConversions und JavaConverters Ihrer Meinung nach veraltet? In der aktuellen Dokumentation 2.11.8 sind beide nicht als veraltet gekennzeichnet und sie enthalten auch keinen Verweis auf 'decorateAll' oder 'wrapAll', der angibt, dass dies die neue und bevorzugte Verwendung ist.
Joost den Boer
@JoostdenBoer Es scheint, dass es in Scala 2.10 einige veraltete Dekorateure gab , obwohl sie mit Scala 2.11 wieder entfernt worden zu sein scheinen.
Stempler
14

Vielleicht möchten Sie auch diese hervorragende Bibliothek erkunden: Scalaj-Sammlung mit bidirektionaler Konvertierung zwischen Java- und Scala-Sammlungen. In Ihrem Fall können Sie Folgendes tun, um eine java.util.List in eine Scala-Liste zu konvertieren:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala
Surya Suravarapu
quelle
1
Diese Bibliothek ist das Beste, was es je gab. Funktioniert wirklich sehr gut.
Michael Neale
6
Scalas JavaConverters ist der richtige Weg, um dies nach einigen Jahren noch einmal zu überprüfen.
Surya Suravarapu
4

Beim Starten ersetzt das Scala 2.13Paket scala.jdk.CollectionConvertersdie Pakete scala.collection.JavaConverters/JavaConversions._:

import scala.jdk.CollectionConverters._

// val javaList: java.util.List[String] = java.util.Arrays.asList("one","two","three")
javaList.asScala
// collection.mutable.Buffer[String] = Buffer("one", "two", "three")
javaList.asScala.toSet
// collection.immutable.Set[String] = Set("one", "two", "three")
Xavier Guihot
quelle
3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])
Jamesqiu
quelle
Dies ist eine großartige Antwort und hat mein Problem gelöst. Die meisten der im Internet erwähnten Methoden konvertieren einfach die (z. B.) java.util.List [java.lang.Long] in scala.collection.immutable.List [java.lang.Long]. Also hat diese Methode für mich funktioniert, um sie in scala.collection.immutable.List [scala.Long] zu konvertieren
ajkl
2

Sie können die Typinformationen im toArray-Aufruf hinzufügen, damit das Set parametrisiert wird:

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

Dies könnte vorteilhaft sein , wenn die Packung Sammlungen wird durch eine große Nacharbeit für Scala gehen 2.8 und das scala.collection.jcl Paket weggeht

Aaron
quelle
1

Sie können die Java-Sammlung in ein Array konvertieren und daraus eine Scala-Liste erstellen:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)
Fabian Steeg
quelle
2
Dies ist nicht besonders gut, da meine java.util.List als parametrisierte Liste aus einer Java-API zurückkommt (mein Aufruf der API ergibt also eine java.util.List <String>). Ich versuche, dies zu ändern in eine Scala unveränderliche HashSet
oxbow_lakes
1

Ein weiterer einfacher Weg, um dieses Problem zu lösen:

import collection.convert.wrapAll._
aleksandr_hramcov
quelle