Konwertowanie kolekcji Java na kolekcję Scala


88

Powiązane z pytaniem o przepełnienie stosu Scala odpowiednik nowego zestawu HashSet (kolekcja) , jak przekonwertować kolekcję Java ( java.util.Listpowiedzmy) na kolekcję Scala List?

W rzeczywistości próbuję przekonwertować wywołanie Java API na Springa SimpleJdbcTemplate , które zwraca java.util.List<T>, na niezmienny Scala HashSet. Na przykład:

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

To wydaje się działać. Krytyka jest mile widziana!

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

Odpowiedzi:


17

Twoja ostatnia sugestia działa, ale możesz też uniknąć używania jcl.Buffer:

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

Zauważ, że scala.collection.immutable.Setjest on domyślnie udostępniany dzięki Predef.scala.


9
Ta sugestia nie działa, gdy chcę zachować informacje o typie
oxbow_lakes

127

Na przyszłość: w Scali 2.8 można to zrobić w następujący sposób:

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

setjest scala.collection.immutable.Set[String]po tym.

Zobacz również odpowiedź Bena Jamesa, aby uzyskać bardziej wyraźny sposób (użycie JavaConverters), który wydaje się być teraz zalecany.


Wygląda na to, że teraz JavaConversionsma pewne implikacje, które sprawiają, że toSetpołączenie nie jest konieczne.
Rajish

@Rajish Myślę, że lepiej, jeśli konwersja jest jawna (patrz stackoverflow.com/questions/8301947/ ... )
krookedking

masz rację, lepiej jest użyć importu scala.collection.JavaConverters._
Abhishek Sengupta

62

Jeśli chcesz być bardziej wyraźny niż JavaConversions pokazane w odpowiedzi robinst , możesz użyć JavaConverters:

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

25

JavaConversions ( odpowiedź robinst ) i JavaConverters (odpowiedź Bena Jamesa ) zostały wycofane ze Scala 2.10 .

Zamiast JavaConversions użyj:

import scala.collection.convert.wrapAll._

zgodnie z sugestią aleksandr_hramcov .

Zamiast JavaConverters użyj:

import scala.collection.convert.decorateAll._

W obu przypadkach istnieje również możliwość zaimportowania samych konwersji / konwerterów odpowiednio do Javy lub Scali, np .:

import scala.collection.convert.wrapAsScala._

Aktualizacja: powyższe stwierdzenie, że JavaConversions i JavaConverters zostały wycofane, wydaje się być błędne. W Scali 2.10 istniały przestarzałe właściwości, co spowodowało ostrzeżenia o wycofaniu podczas ich importowania. Więc alternatywne importy tutaj wydają się być tylko aliasami. Chociaż nadal je wolę, ponieważ IMHO nazwy są bardziej odpowiednie.


Dlaczego twierdzisz, że JavaConversions i JavaConverters są przestarzałe? W aktualnej dokumentacji 2.11.8 oba nie są oznaczone jako przestarzałe, a także nie mają odniesienia do „decorateAll” lub „wrapAll” stwierdzającego, że jest to nowe i preferowane użycie.
Joost den Boer

@JoostdenBoer Wygląda na to, że w Scali 2.10 było kilka przestarzałych dekoratorów , chociaż wydaje się, że zostały one ponownie usunięte w Scali 2.11.
stempler

14

Możesz również chcieć zbadać tę doskonałą bibliotekę: kolekcję scalaj, która ma dwukierunkową konwersję między kolekcjami Java i Scala. W twoim przypadku, aby przekonwertować java.util.List na Scala List, możesz to zrobić:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala

1
Ta biblioteka to najwspanialsza rzecz w historii. Naprawdę działa dobrze.
Michael Neale

7
Wracając do tego po kilku latach, JavaConverters firmy Scala jest drogą do zrobienia.
Surya Suravarapu

5

Uruchamianie Scala 2.13, pakiet scala.jdk.CollectionConverterszastępuje pakiety 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")

3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])

to świetna odpowiedź i rozwiązała mój problem. Większość metod wymienionych w Internecie po prostu konwertuje (np.) Java.util.List [java.lang.Long] na scala.collection.immutable.List [java.lang.Long]. Więc ta metoda zadziałała, aby przekonwertować ją na scala.collection.immutable.List [scala.Long]
ajkl

2

Możesz dodać informacje o typie w wywołaniu toArray, aby ustawić parametry zestawu:

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

Może to być korzystne, ponieważ pakiet zbiory przeżywa poważnych przeróbek do Scala 2.8 i pakiet scala.collection.jcl jest odchodzi


1

Możesz przekonwertować kolekcję Java na tablicę, a następnie utworzyć listę Scala z tego:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)

2
To nie jest świetne, ponieważ moja java.util.List wraca z interfejsu API Java jako sparametryzowana lista (więc moje wywołanie interfejsu API daje java.util.List <String>) - próbuję to zmienić into a scala immutable HashSet
oxbow_lakes

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.