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

В scala.collection есть два очень похожих объекта JavaConversions и _ 3_.

  • В чем разница между этими двумя объектами?
  • Почему они оба существуют?
  • Когда я хочу использовать одно против другого?

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 основаны на Scope, поэтому, если вы не 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
Можно ли использовать JavaConverters изнутри java? (например, у меня есть java.util.List и API, для которого требуется набор scala, и я пишу код 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 и _8 _...

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