Mengonversi koleksi Java menjadi koleksi Scala

88

Terkait dengan pertanyaan Stack Overflow, Scala setara dengan HashSet (Koleksi) baru , bagaimana cara mengonversi koleksi Java ( java.util.Listkatakanlah) menjadi koleksi Scala List?

Saya sebenarnya mencoba untuk mengubah panggilan API Java ke Spring SimpleJdbcTemplate , yang mengembalikan java.util.List<T>, menjadi Scala yang tidak dapat diubah HashSet. Jadi contohnya:

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

Sepertinya ini berhasil. Kritik diterima!

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

Jawaban:

17

Saran terakhir Anda berfungsi, tetapi Anda juga dapat menghindari penggunaan jcl.Buffer:

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

Perhatikan bahwa scala.collection.immutable.Settersedia secara default berkat Predef.scala.

Jorge Ortiz
sumber
9
Saran ini tidak berfungsi di mana saya ingin menyimpan informasi jenis
oxbow_lakes
127

Untuk referensi di masa mendatang: Dengan Scala 2.8, dapat dilakukan seperti ini:

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

setadalah scala.collection.immutable.Set[String]setelah ini.

Juga lihat jawaban Ben James untuk cara yang lebih eksplisit (menggunakan JavaConverters), yang sepertinya direkomendasikan sekarang.

Robinst
sumber
Sepertinya sekarang JavaConversionsmemiliki beberapa implikasi membuat toSetpanggilan tidak perlu.
Rajish
@Rajish Saya pikir lebih baik jika konversinya eksplisit (lihat stackoverflow.com/questions/8301947/… )
krookedking
Anda benar, sebaiknya gunakan import scala.collection.JavaConverters._
Abhishek Sengupta
62

Jika Anda ingin lebih eksplisit daripada JavaConversions yang ditunjukkan dalam jawaban robinst , Anda dapat menggunakan JavaConverters:

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

JavaConversions ( jawaban robinst ) dan JavaConverters ( jawaban Ben James ) tidak lagi digunakan dengan Scala 2.10 .

Sebagai ganti penggunaan JavaConversions :

import scala.collection.convert.wrapAll._

seperti yang disarankan oleh aleksandr_hramcov .

Sebagai ganti penggunaan JavaConverters :

import scala.collection.convert.decorateAll._

Untuk keduanya juga ada kemungkinan untuk hanya mengimpor konversi / konverter ke Java atau Scala, misalnya:

import scala.collection.convert.wrapAsScala._

Pembaruan: Pernyataan di atas bahwa JavaConversions dan JavaConverters sudah tidak digunakan lagi tampaknya salah. Ada beberapa properti yang tidak digunakan lagi di Scala 2.10, yang mengakibatkan peringatan penghentian saat mengimpornya. Jadi impor alternatif di sini sepertinya hanya alias. Padahal saya masih lebih suka mereka, karena IMHO namanya lebih sesuai.

stempler
sumber
Mengapa Anda mengatakan JavaConversions dan JavaConverters tidak digunakan lagi? Dalam dokumentasi saat ini 2.11.8, keduanya tidak ditandai sebagai usang dan juga tidak memiliki referensi ke 'decorateAll' atau 'wrapAll' yang menyatakan bahwa itu adalah penggunaan baru dan pilihan.
Joost den Boer
@JoostdenBoer Tampaknya ada beberapa dekorator yang ditinggalkan di sana di Scala 2.10, meskipun mereka tampaknya telah dihapus lagi dengan Scala 2.11.
stempler
14

Anda mungkin juga ingin menjelajahi perpustakaan luar biasa ini: koleksi scalaj yang memiliki konversi dua arah antara koleksi Java dan Scala. Dalam kasus Anda, untuk mengonversi daftar java.util.List ke Daftar Scala, Anda dapat melakukan ini:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala
Surya Suravarapu
sumber
1
Perpustakaan itu adalah yang terbesar yang pernah ada. Benar-benar bekerja dengan baik.
Michael Neale
7
Meninjau kembali ini setelah beberapa tahun, JavaConverters Scala adalah cara yang tepat.
Surya Suravarapu
5

Memulai Scala 2.13, paket scala.jdk.CollectionConvertersmenggantikan paket 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
sumber
3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])
jamesqiu
sumber
ini adalah jawaban yang bagus dan memecahkan masalah saya. Sebagian besar metode yang disebutkan di internet hanya mengonversi (misalnya) java.util.List [java.lang.Long] ke scala.collection.immutable.List [java.lang.Long]. Jadi metode ini berhasil bagi saya untuk mengubahnya menjadi scala.collection.immutable.List [scala.Long]
ajkl
2

Anda dapat menambahkan informasi tipe dalam panggilan toArray untuk membuat Set menjadi parameter:

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

Ini mungkin lebih disukai karena paket koleksi akan melalui pengerjaan ulang besar untuk Scala 2.8 dan paket scala.collection.jcl akan ditiadakan

Aaron
sumber
1

Anda bisa mengonversi koleksi Java ke array dan kemudian membuat daftar Scala dari itu:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)
Fabian Steeg
sumber
2
Ini tidak bagus karena java.util.List saya keluar dari Java API sebagai daftar parametrized (jadi panggilan saya ke API menghasilkan java.util.List <String>) - Saya mencoba mengubahnya menjadi skala HashSet yang tidak berubah
oxbow_lakes
1

Cara sederhana lain untuk mengatasi masalah ini:

import collection.convert.wrapAll._
aleksandr_hramcov
sumber