Преобразование коллекции Java в коллекцию Scala

В связи с вопросом о переполнении стека Scala-эквивалент нового HashSet (Collection), как преобразовать коллекцию Java (java.util.List скажем) в коллекцию Scala List?

На самом деле я пытаюсь преобразовать вызов Java API в Spring SimpleJdbcTemplate, который возвращает java.util.List<T>, в Неизменяемый Scala HashSet. Так например:

val l: java.util.List[String] = javaApi.query( ... )
val s: HashSet[String] = //make a set from l

Кажется, это работает. Критика приветствуется!

import scala.collection.immutable.Set
import scala.collection.jcl.Buffer 
val s: scala.collection.Set[String] =
                      Set(Buffer(javaApi.query( ... ) ) : _ *)

person oxbow_lakes    schedule 23.03.2009    source источник


Ответы (10)


Ваше последнее предложение работает, но вы также можете избежать использования jcl.Buffer:

Set(javaApi.query(...).toArray: _*)

Обратите внимание, что scala.collection.immutable.Set доступен по умолчанию благодаря Predef.scala.

person Jorge Ortiz    schedule 24.03.2009
comment
Это предложение не работает там, где я хочу сохранить информацию о типе - person oxbow_lakes; 24.03.2009

Для справки в будущем: в Scala 2.8 это можно было бы сделать так:

import scala.collection.JavaConversions._
val list = new java.util.ArrayList[String]()
list.add("test")
val set = list.toSet

set - это scala.collection.immutable.Set[String] после этого.

Более подробный способ ( using JavaConverters), который сейчас рекомендуется.

person robinst    schedule 19.10.2010
comment
Похоже, что теперь JavaConversions имеет некоторые последствия, делающие вызов toSet ненужным. - person Rajish; 22.08.2012
comment
@Rajish Я думаю, что лучше, если преобразование будет явным (см. stackoverflow.com/questions/8301947/) - person krookedking; 17.03.2014
comment
вы правы, лучше использовать import scala.collection.JavaConverters._ - person Abhishek Sengupta; 31.05.2020

Если вы хотите быть более явным, чем JavaConversions, продемонстрированные в ответ robinst, вы можете использовать JavaConverters:

import scala.collection.JavaConverters._
val l = new java.util.ArrayList[java.lang.String]
val s = l.asScala.toSet
person Ben James    schedule 15.06.2011

JavaConversions (ответ robinst) и JavaConverters (ответ Бена Джеймса) устарели в Scala 2.10.

Вместо JavaConversions используйте:

import scala.collection.convert.wrapAll._

как предлагает aleksandr_hramcov.

Вместо JavaConverters используйте:

import scala.collection.convert.decorateAll._

Для обоих также есть возможность импортировать только преобразования / преобразователи в Java или Scala соответственно, например:

import scala.collection.convert.wrapAsScala._

Обновление. Приведенное выше утверждение о том, что JavaConversions и JavaConverters устарели, кажется неправильным. В Scala 2.10 были некоторые устаревшие свойства, из-за которых при их импорте появлялись предупреждения об устаревании. Таким образом, альтернативный импорт здесь, кажется, только псевдонимы. Хотя я все же предпочитаю их, так как ИМХО названия более подходящие.

person stempler    schedule 18.08.2014
comment
Почему вы говорите, что JavaConversions и JavaConverters устарели? В текущей документации 2.11.8 оба не помечены как устаревшие, и в них также нет ссылки на decorateAll или wrapAll, указывающую, что это новое и предпочтительное использование. - person Joost den Boer; 24.08.2016
comment
@JoostdenBoer Похоже, были устаревшие декораторы есть в Scala 2.10, хотя кажется, что они снова были удалены в Scala 2.11. - person stempler; 25.08.2016

Вы также можете изучить эту отличную библиотеку: scalaj-collection, которая имеет двустороннее преобразование между Java. и коллекции Scala. В вашем случае, чтобы преобразовать java.util.List в Scala List, вы можете сделать это:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala
person Surya Suravarapu    schedule 12.05.2010
comment
Эта библиотека - величайшая вещь на свете. Действительно действительно хорошо работает. - person Michael Neale; 09.10.2010
comment
Возвращаясь к этому через пару лет, можно сказать, что JavaConverters в Scala - это то, что нужно. - person Surya Suravarapu; 30.06.2012

Начиная с Scala 2.13, упакуйте _2 _ заменяет пакеты 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")
person Xavier Guihot    schedule 29.03.2019

Вы можете добавить информацию о типе в вызов toArray, чтобы параметризовать Set:

 val s = Set(javaApi.query(....).toArray(new Array[String](0)) : _*)

Это может быть предпочтительнее, поскольку пакет коллекций подвергается серьезной переработке для Scala 2.8, а пакет scala.collection.jcl - уйти

person Aaron    schedule 23.03.2010

Вы можете преобразовать коллекцию Java в массив, а затем создать из этого список Scala:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)
person Fabian Steeg    schedule 23.03.2009
comment
Это не очень хорошо, потому что мой java.util.List возвращается из Java API в виде параметризованного списка (поэтому мой вызов API дает java.util.List ‹String›) - я пытаюсь включить это в неизменяемый HashSet Scala - person oxbow_lakes; 23.03.2009

Еще один простой способ решить эту проблему:

import collection.convert.wrapAll._
person aleksandr_hramcov    schedule 07.03.2014

person    schedule
comment
это отличный ответ и решил мою проблему. Большинство методов, упомянутых в Интернете, просто преобразуют (например) java.util.List [java.lang.Long] в scala.collection.immutable.List [java.lang.Long]. Итак, этот метод помог мне преобразовать его в scala.collection.immutable.List [scala.Long] - person ajkl; 21.12.2014