Преобразование коллекции Java в коллекцию Scala
Связанный с вопросом переполнения стека Scala-эквивалент нового HashSet (Collection), как мне преобразовать Java-коллекцию (java.util.List
скажем) в коллекцию Scala List
?
Я на самом деле пытаюсь преобразовать вызов API Java в Spring SimpleJdbcTemplate
, который возвращает java.util.List<T>
в неизменном Скала 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( ... ) ) : _ *)
9 ответов
Ваше последнее предложение работает, но вы также можете избежать использования jcl.Buffer
:
Set(javaApi.query(...).toArray: _*)
Обратите внимание, что scala.collection.immutable.Set
по умолчанию доступен Predef.scala
,
Для дальнейшего использования: в 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]
после этого.
Также см. Ответ Бена Джеймса для более явного способа (с использованием JavaConverters), который, кажется, рекомендуется сейчас.
Если вы хотите быть более явным, чем JavaConversions, продемонстрированные в ответе Робинста, вы можете использовать JavaConverters:
import scala.collection.JavaConverters._
val l = new java.util.ArrayList[java.lang.String]
val s = l.asScala.toSet
JavaConversions ( ответ Робинста) и JavaConverters ( ответ Бена Джеймса) устарели в Scala 2.10.
Вместо JavaConversions используйте:
import scala.collection.convert.wrapAll._
по предложению Александра Храмцова.
Вместо JavaConverters используйте:
import scala.collection.convert.decorateAll._
Для обоих есть также возможность импортировать только преобразования / конвертеры в Java или Scala соответственно, например:
import scala.collection.convert.wrapAsScala._
Обновление: утверждение выше о том, что JavaConversions и JavaConverters устарели, кажется неверным. В Scala 2.10 были некоторые устаревшие свойства, что приводило к появлению предупреждений об устаревании при их импорте. Таким образом, альтернативный импорт здесь представляется только псевдонимами. Хотя я все же предпочитаю их, так как ИМХО имена более уместны.
Вы также можете изучить эту превосходную библиотеку: 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
Начало Scala 2.13
пакет scala.jdk.CollectionConverters
заменяет пакеты scala.collection.JavaConverters/JavaConversions._
:
import scala.jdk.CollectionConverters.Ops._
// 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")
val array = java.util.Arrays.asList("one","two","three").toArray
val list = array.toList.map(_.asInstanceOf[String])
Вы можете добавить информацию о типе в вызове toArray, чтобы сделать Set параметризованным:
val s = Set(javaApi.query(....).toArray(new Array[String](0)) : _*)
Это может быть предпочтительнее, так как пакет коллекций проходит серьезную переработку для Scala 2.8, а пакет scala.collection.jcl уходит.
Еще один простой способ решить эту проблему:
import collection.convert.wrapAll._
Вы можете преобразовать коллекцию Java в массив, а затем создать список Scala из этого:
val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)