Каква е разликата между JavaConverters и JavaConversions в Scala?

В scala.collection има два много подобни обекта JavaConversions и JavaConverters.

  • Каква е разликата между тези два обекта?
  • Защо съществуват и двете?
  • Кога искам да използвам едното срещу другото?

person Michael Ekstrand    schedule 28.11.2011    source източник


Отговори (4)


РЕДАКТИРАНЕ: Java Conversions получи @deprecated в Scala 2.13.0. Вместо това използвайте scala.jdk.CollectionConverters.

JavaConversions предоставя серия от неявни методи, които преобразуват между колекция на Java и най-близката съответстваща колекция на Scala и обратно. Това се прави чрез създаване на обвивки, които имплементират или интерфейса на Scala и препращат повикванията към основната колекция на Java, или интерфейсът на Java, препращайки повикванията към основната колекция на Scala.

JavaConverters използва модела pimp-my-library, за да „добави“ метода asScala към колекциите на Java и метода asJava към колекциите на Scala, които връщат подходящите обвивки, обсъдени по-горе. Той е по-нов (от версия 2.8.1) от JavaConversions (от 2.8) и прави преобразуването между Scala и Java колекция изрично. Противно на това, което Дейвид пише в отговора си, бих ви препоръчал да си създадете навик да използвате JavaConverters, тъй като ще бъде много по-малко вероятно да пишете код, който прави много неявни реализации, тъй като можете да контролирате единственото място, където това ще се случи: където пишете .asScala или .asJava.

Ето методите за преобразуване, които JavaConverters предоставя:

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]

За да използвате преобразуванията директно от Java обаче, по-добре е да извиквате директно методи от JavaConversions; напр.:

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
person Jean-Philippe Pellet    schedule 28.11.2011
comment
Здравей Жан-Филип. Не разбирам мнението ви относно имплицитното преобразуване. Както обяснихте, ScalaConverter използва имплицитни числа, за да добави asJava и asScala. Освен това вие посочвате типа scala или java, към който искате да конвертирате, в новата дефиниция на val (т.е. val sl = new scala.collection.mutable.ListBuffer[Int]; val jl : java.util.List[Int] = sl). Така че с помощта на ScalaConversions имате лесен начин да конвертирате вашата колекция и възможност за фина настройка на целевия тип. - person David; 29.11.2011
comment
Да, използвайте JavaConverters над JavaConversions,. Но също така обмислете използването на github.com/scalaj/scalaj-collection, тъй като има някои предимства като конвертиране java.util.List to Seq. (Горният списък от 2.8.1 ли е?) - person oluies; 29.11.2011
comment
@David Въпреки че неявните преобразувания като тези, предоставени от JavaConversions са удобни, може бързо да пренебрегнете всички места, където те могат да бъдат вмъкнати от компилатора. Вие контролирате тези места с JavaConverters. Това е цялата дискусия за имплицитно срещу експлицитно преобразуване. - person Jean-Philippe Pellet; 29.11.2011
comment
@Jean-PhilippePellet имплицитните преобразувания в Scala са базирани на обхват, така че ако не import JavaConversions._, преобразувания няма да се появят, така че вие ​​имате контрол върху това, което се преобразува. Ако поставите импортирането по правилния начин (само когато е необходимо), имате пълен контрол върху това къде се извършва преобразуването. - person David; 29.11.2011
comment
@David … и с JavaConverters имате допълнителната безопасност, че нищо не се случва, освен ако не го напишете изрично. Това е допълнителна сигурност и най-вероятно затова е добавен този клас. - person Jean-Philippe Pellet; 29.11.2011
comment
Човек би си помислил, че именуването би било по-добро: напр. нещо като JavaConversionsImplicit и JavaConversionsExplicit би било по-лесно за разграничаване. - person Raman; 25.10.2012
comment
Използваеми ли са Java конверторите от java? (напр. имам java.util.List и API, който изисква scala Set и пиша java код) - person The Trav; 08.11.2013
comment
@TheTrav Добавих пример в Java. Мисля, че е по-добре да използвате JavaConversions, ако е от Java. - person Jean-Philippe Pellet; 08.11.2013
comment
За съжаление мисля, че който и да е създал тези класове, е бил убит с камъни. JavaConversions е много хубаво, но не ви дава начин да създавате неизменни scala колекции, а toMap бита на JavaConverters са PITA за работа. - person Shadow Man; 26.03.2014

За всеки, който се занимава с този въпрос след Scala 2.12.x, JavaConversions вече е отхвърлен и JavaConverters е предпочитаният метод.

person Ryan Burke    schedule 18.01.2017
comment
От Scala 2.13, JavaConverters е отхвърлен, а scala.jdk.CollectionConverters е предпочитаният метод ;) - person antonone; 16.02.2020

В Scala 2.13 JavaConverters са отхвърлени в полза на scala.jdk.CollectionConverters:

...нов пакет scala.jdk с обекти CollectionConverters (класически Java колекции, подобни на collection.JavaConverters във 2.12), StreamConverters, FunctionConverters и OptionConverters...

person Mario Galic    schedule 25.06.2019

Както е обяснено в API, JavaConversions е набор от неявни преобразувания, който трансформира java колекции в свързана scala колекция.

Можете да го използвате с import collection.JavaConversions._. Когато е необходимо, компилаторът автоматично ще трансформира java колекцията в правилния тип scala.

JavaConverters са набор от декоратори, които помагат за трансформирането java или scala колекции към scala или java колекции с помощта на asScala или asJava методи, които ще бъдат имплицитно добавени към колекцията, която искате да трансформирате. За да използвате тези конвертори, трябва да импортирате:

import collection.JavaConverters._

Трябва да предпочетете JavaConversions, тъй като обикновено е по-лесен за използване (няма нужда да използвате asScala или asJava).

person David    schedule 28.11.2011
comment
Докато използването на напълно имплицитния подход на JavaConverters е по-лесно за писане, е по-трудно за четене. Текущият стил на Scala предполага, че е по-добре изрично да се извикват методи за извършване на преобразувания, поради което сега се предпочитат JavaConverters. - person Leif Wickland; 06.09.2013
comment
JavaConversions са отхвърлени в Scala 2.12 - person Andrzej Wąsowski; 12.01.2019