В чем разница между JavaConverters и JavaConversion в Scala?

Ответы:

253

РЕДАКТИРОВАТЬ: 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
Жан-Филипп Пелле
источник
5
Да, используйте JavaConverters поверх JavaConversions. Но также рассмотрите возможность использования github.com/scalaj/scalaj-collection, поскольку у него есть некоторые преимущества, такие как преобразование java.util.List в Seq. (Вышеприведенный список из 2.8.1?)
oluies 28.11.11
7
@David Хотя неявные преобразования, подобные предоставленным JavaConversions, удобны, вы можете быстро пропустить все места, где они могут быть вставлены компилятором. Вы контролируете эти места с JavaConverters. Это целая дискуссия о неявном и явном преобразовании.
Жан-Филипп Пелле
1
@ Jean-PhilippePellet неявные преобразования в Scala основаны на Scope, поэтому, если вы этого не сделаете import JavaConversions._, преобразования не произойдут, так что вы можете контролировать, что преобразовано. Если вы разместите импорт правильно (только при необходимости), у вас будет полный контроль над тем, где выполняется преобразование.
Дэвид
2
@ Дэвид ... и с JavaConvertersтобой есть дополнительная безопасность, что ничего не случится, если ты не напишешь это явно. Это дополнительная защита, и, скорее всего, именно поэтому этот класс был добавлен.
Жан-Филипп Пелле
23
Вы могли бы подумать, что наименование будет лучше: например, что-то вроде «JavaConversionsImplicit» и «JavaConversionsExplicit» было бы легче различить.
Раман
52

Для тех, кто интересуется этим вопросом, начиная с Scala 2.12.x, JavaConversionsон устарел и JavaConvertersявляется предпочтительным методом.

Райан Берк
источник
2
Так как Scala 2.13 JavaConvertersустарела и scala.jdk.CollectionConvertersявляется предпочтительным методом;)
антонон
4

В Scala 2.13, JavaConvertersбыли устаревшими в пользу scala.jdk.CollectionConverters:

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

Марио Галич
источник
3

Как объясняется в API, JavaConversionsэто набор неявных преобразований, который преобразует Java-коллекции в связанную Scala-коллекцию.

Вы можете использовать его с import collection.JavaConversions._. При необходимости компилятор автоматически преобразует коллекцию java в правильный тип scala.

JavaConvertersнабор декораторов, который помогает преобразовывать коллекции java или scala в коллекции scala или java, используя методы asScalaили asJavaметоды, которые будут неявно добавлены в коллекцию, которую вы хотите преобразовать. Чтобы использовать эти конвертеры, вам необходимо импортировать:

import collection.JavaConverters._

Вы должны предпочесть, так JavaConversionsкак это обычно проще в использовании (не нужно использовать asScalaили asJava).

Дэвид
источник
15
Хотя использование полностью неявного подхода JavaConverters проще для написания, его труднее читать. Текущий стиль Scala предполагает, что лучше явно вызывать методы для выполнения преобразований, поэтому JavaConverters сейчас предпочтительнее.
Лейф Викленд
JavaConversions устарели в Scala 2.12
Анджей Весовски