2009-03-23 3 views
83

Связанные с переполнением стека вопрос Scala equivalent of new HashSet(Collection), как преобразовать коллекцию Java (java.util.List говорят) в коллекции Scala List?Преобразование коллекции Java в коллекции Скала

Я на самом деле пытается преобразовать вызов API Java для Spring'sSimpleJdbcTemplate, который возвращает 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(...)) : _ *) 

ответ

16

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

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

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

+9

Это предложение не работает, где я хочу сохранить информацию о типе –

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 ) - я пытаюсь повернуть это в scala immutable HashSet –

2

Вы можете добавить информацию о типе в ToArray называют, чтобы сделать набор параметрироваться:

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

Это может быть предпочтительным, так как пакет коллекции происходит через основные переделки для Scala 2.8 и scala.collection .jcl package is going away

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

Эта библиотека - величайшая вещь когда-либо. Действительно действительно работает хорошо. –

+4

Повторяя это через пару лет, JavaConverters Scala - это путь. –

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

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

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

120

Для дальнейшего использования: С 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] после этого.

Также см. Ben James' answer для более ясного способа (с использованием JavaConverters), который, как представляется, рекомендуется сейчас.

+1

Работает как шарм почти каждый раз! –

+7

@oxbow_lakes Я думаю, что пришло время отметить этот ответ как принятый. –

+0

Похоже, что теперь 'JavaConversions' имеет некоторые признаки, что делает вызов' toSet' необязательным. – Rajish

57

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

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

Ввод в этом code verbatim (да, включая строку импорта) выдает следующее в REPL: error: значение asScala не является членом java.util.ArrayList [java.lang.String] " – robbbbbb

+1

К сожалению, я пропустил шаблон' ._' от импорта. Исправлена. –

2

Другой простой способ решить эту проблему:

import collection.convert.wrapAll._ 
25

JavaConversions (robinst's answer) и JavaConverters (Ben James's answer) устарели с Scala 2.10.

Вместо JavaConversions Использование:

import scala.collection.convert.wrapAll._ 

как предложено aleksandr_hramcov.

Вместо JavaConverters Использование:

import scala.collection.convert.decorateAll._ 

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

import scala.collection.convert.wrapAsScala._ 

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

+0

Почему вы говорите, что JavaConversions и JavaConverters устарели? В текущей документации 2.11.8 обе они не отмечены как устаревшие, и у них также нет ссылки на «decorateAll» или «wrapAll», заявив, что это новое и предпочтительное использование. –

+0

@JoostdenBoer Кажется, в Scala 2.10 были некоторые устаревшие декораторы [https://github.com/scala/scala/blob/2.10.x/src/library/scala/collection/JavaConverters.scala), хотя они кажутся снова удалить с помощью Scala 2.11. – stempler

Смежные вопросы