Apa perbedaan antara JavaConverters dan JavaConversions di Scala?

Jawaban:

253

EDIT: Java Conversionsmasuk @deprecatedScala 2.13.0. Gunakan scala.jdk.CollectionConverters sebagai gantinya.

JavaConversionsmenyediakan serangkaian metode implisit yang mengkonversi antara koleksi Java dan koleksi Scala terkait terdekat, dan sebaliknya. Ini dilakukan dengan membuat pembungkus yang mengimplementasikan antarmuka Scala dan meneruskan panggilan ke koleksi Java yang mendasarinya, atau antarmuka Java, meneruskan panggilan ke koleksi Scala yang mendasarinya.

JavaConvertersmenggunakan pola mucikari perpustakaan saya untuk "menambahkan" asScalametode ke koleksi Java dan asJavametode ke koleksi Scala, yang mengembalikan pembungkus yang sesuai dibahas di atas. Ini lebih baru (sejak versi 2.8.1) daripada JavaConversions(sejak 2.8) dan membuat konversi antara koleksi Scala dan Java eksplisit. Berlawanan dengan apa yang ditulis David dalam jawabannya, saya sarankan Anda membiasakan diri untuk menggunakannya JavaConverterskarena Anda akan lebih kecil kemungkinannya untuk menulis kode yang menghasilkan banyak konversi tersirat, karena Anda dapat mengontrol satu-satunya tempat di mana hal itu akan terjadi : tempat Anda menulis .asScalaatau .asJava.

Inilah metode konversi yang JavaConvertersmenyediakan:

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]

Untuk menggunakan konversi langsung dari Jawa, Anda lebih baik memanggil metode dari JavaConversionslangsung; misalnya:

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
sumber
5
Ya, gunakan JavaConverters melalui JavaConversions ,. Tetapi juga pertimbangkan untuk menggunakan github.com/scalaj/scalaj-collection karena memiliki beberapa manfaat sebagai konversi java.util.List ke Seq. (Apakah daftar di atas dari 2.8.1?)
oluies
7
@ David Sementara konversi implisit seperti yang disediakan oleh JavaConversionsnyaman, Anda dapat dengan cepat mengabaikan semua tempat di mana mereka dapat dimasukkan oleh kompiler. Anda mengendalikan tempat-tempat itu dengan JavaConverters. Ini adalah seluruh diskusi tentang konversi implisit vs eksplisit.
Jean-Philippe Pellet
1
@Jean-PhilippePellet konversi tersirat dalam Scala adalah berbasis Lingkup jadi jika Anda tidak import JavaConversions._, konversi tidak akan terjadi sehingga Anda memiliki kendali atas apa yang dikonversi. Jika Anda menempatkan impor dengan cara yang benar (hanya jika diperlukan), Anda memiliki kendali penuh atas di mana konversi dilakukan.
David
2
@ David ... dan bersama JavaConvertersAnda memiliki keamanan tambahan yang tidak ada yang terjadi kecuali Anda menulisnya secara eksplisit. Itu keamanan tambahan, dan itulah kemungkinan besar mengapa kelas ini ditambahkan.
Jean-Philippe Pellet
23
Anda akan berpikir penamaan akan lebih baik: misalnya sesuatu seperti "JavaConversionsImplicit" dan "JavaConversionsExplicit" akan lebih mudah dibedakan.
Raman
52

Bagi siapa pun yang menggunakan pertanyaan ini sejak Scala 2.12.x, JavaConversionssekarang sudah usang dan JavaConvertersmerupakan metode yang disukai.

Ryan Burke
sumber
2
Sejak Scala 2.13, JavaConverterssudah usang, dan scala.jdk.CollectionConvertersmerupakan metode yang disukai;)
antonone
4

Dalam Scala 2.13, JavaConverterstelah tidak digunakan lagi karena scala.jdk.CollectionConverters:

... paket baru scala.jdkdengan objek CollectionConverters (koleksi Java klasik, mirip dengan collection.JavaConvertersdi 2.12) StreamConverters,, FunctionConvertersdan OptionConverters...

Mario Galic
sumber
3

Sebagaimana dijelaskan dalam API, JavaConversionsadalah serangkaian konversi implisit yang mengubah koleksi java menjadi koleksi scala terkait.

Anda dapat menggunakannya dengan import collection.JavaConversions._. Bila perlu, kompiler akan secara otomatis mengubah koleksi java menjadi jenis scala yang tepat.

JavaConvertersadalah seperangkat dekorator yang membantu mengubah koleksi java atau scala ke scala atau koleksi java menggunakan asScalaatau asJavametode yang akan ditambahkan secara implisit ke koleksi yang ingin Anda ubah. Untuk menggunakan konverter ini, Anda perlu mengimpor:

import collection.JavaConverters._

Anda harus memilih JavaConversionskarena umumnya lebih mudah digunakan (tidak perlu menggunakan asScalaatau asJava).

David
sumber
15
Meskipun menggunakan pendekatan yang sepenuhnya implisit dari JavaConverters lebih mudah untuk ditulis, lebih sulit untuk dibaca. Gaya Scala saat ini menunjukkan bahwa lebih baik memanggil metode secara eksplisit untuk melakukan konversi, itulah sebabnya JavaConverters sekarang lebih disukai.
Leif Wickland
Konversi Java tidak digunakan lagi dalam Scala 2.12
Andrzej Wąsowski