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( ... ) ) : _ *)

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.


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.


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

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.


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

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")

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

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

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


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)

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.