Перетворення колекції Java у колекцію Scala


88

Пов’язане із запитанням про переповнення стека Scala, еквівалент нового HashSet (Collection) , як перетворити колекцію Java ( java.util.Listскажімо) у колекцію Scala List?

Я насправді намагаюся перетворити виклик API Java на Spring SimpleJdbcTemplate , який повертає a 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( ... ) ) : _ *)

Відповіді:


17

Ваша остання пропозиція працює, але ви також можете уникнути використання jcl.Buffer:

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

Зауважте, що scala.collection.immutable.Setза замовчуванням доступний завдяки Predef.scala.


9
Ця пропозиція не працює там, де я хочу зберігати інформацію про тип
oxbow_lakes

127

Для подальшого використання: із 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деякі наслідки роблять toSetдзвінок непотрібним.
Раджіш

@Rajish Я думаю , що краще , якщо перетворення явно (див stackoverflow.com/questions/8301947 / ... )
krookedking

ти маєш рацію, краще використовувати імпорт scala.collection.JavaConverters._
Абхішек Сенгупта

62

Якщо ви хочете бути більш явним, ніж JavaConversions, продемонстровані у відповіді robinst , ви можете використовувати JavaConverters:

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

25

JavaConversions (відповідь Робінста ) та 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 було кілька застарілих властивостей, що призводило до попереджень про припинення їх імпорту. Тож альтернативний імпорт тут здається лише псевдонімами. Хоча я все ще віддаю їм перевагу, оскільки назви IMHO є більш доречними.


Чому ви вважаєте, що JavaConversions та JavaConverters застаріли? У поточній документації 2.11.8 обидва вони не позначені як застарілі, і вони також не мають посилання на 'decorationAll' або 'wrapAll', вказуючи, що це нове та бажане використання.
Joost den Boer

@JoostdenBoer Здається , там були деякі застарілі декоратори там в Scala 2.10, хоча вони , здається, були знову вилучені Scala 2.11.
stempler

14

Можливо, ви захочете вивчити цю чудову бібліотеку: scalaj-collection, яка має двостороннє перетворення між колекціями Java і Scala. У вашому випадку для перетворення java.util.List у список Scala ви можете зробити це:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala

1
Ця бібліотека - це найбільше, що коли-небудь було. Дійсно дійсно добре працює.
Michael Neale

6
Переглянувши це через кілька років, JavaConverters Scala - це шлях.
Сурья Сураварапу

4

Запускаючи Scala 2.13, пакунок scala.jdk.CollectionConvertersзамінює пакети 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")

3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])

це чудова відповідь і вирішила мою проблему. Більшість методів, згаданих в Інтернеті, просто перетворюють (наприклад) java.util.List [java.lang.Long] у scala.collection.immutable.List [java.lang.Long]. Тож цей метод спрацював для мене, щоб перетворити його на scala.collection.immutable.List [scala.Long]
ajkl

2

Ви можете додати інформацію про тип у виклик toArray, щоб зробити параметризованим Set:

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

Це може бути кращим, оскільки пакет колекцій проходить серйозну переробку для Scala 2.8, а пакет scala.collection.jcl - відпадає


1

Ви можете перетворити колекцію Java у масив, а потім створити список Scala з цього:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)

2
Це не чудово, тому що мій java.util.List повертається з Java API як параметризований список (тому мій виклик API дає java.util.List <String>) - я намагаюся перетворити це в масштабний незмінний HashSet
oxbow_lakes

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.