Создайте неизменный список из java.lang.Iterator - PullRequest
22 голосов
/ 16 мая 2011

Я использую библиотеку ( JXPath ), чтобы запросить граф бобов для извлечения соответствующих элементов.Однако JXPath возвращает группы совпадающих элементов в качестве экземпляра java.lang.Iterator, и я бы предпочел преобразовать его в неизменяемый список scala.Есть ли более простой способ сделать, чем перебирать итератор и создавать новый неизменный список на каждом шаге итерации?

Ответы [ 2 ]

33 голосов
/ 16 мая 2011

Возможно, вы захотите переосмыслить потребность в List, хотя он выглядит очень знакомым при переходе с Java, и List является реализацией неизменяемого Seq по умолчанию, часто это не лучший выбор для коллекции.

Операции, для которых этот список является оптимальным, уже доступны через итератор (в основном, с использованием последовательных элементов заголовка и предваряющих элементов).Если итератор уже не дает вам то, что вам нужно, то я могу в значительной степени гарантировать, что List не будет вашим лучшим выбором - вектор будет более подходящим.


Получив этоспособ ... Рекомендованный метод для преобразования между коллекциями Java и Scala (начиная с Scala 2.8.1) - это scala.collection.JavaConverters.Это дает вам больше контроля, чем JavaConversions, и позволяет избежать некоторых возможных неявных конфликтов.

У вас не будет прямого неявного преобразования таким образом.Вместо этого вы получаете методы asScala и asJava, в которые встроены коллекции, что позволяет явно выполнять преобразования.

Чтобы преобразовать итератор Java в итератор Scala:

javaIterator.asScala

Впреобразовать итератор Java в список Scala (с помощью итератора scala):

javaIterator.asScala.toList

Вы также можете рассмотреть возможность преобразования toSeq вместо toList.В случае итераторов это вернет Stream - что позволит вам сохранить ленивое поведение итераторов в более богатом Seq интерфейсе.

РЕДАКТИРОВАТЬ: Там нет toVector метод, но (как указал Даниэль) есть метод toIndexedSeq, который возвращает Vector в качестве подкласса IndexedSeq по умолчанию (точно так же, как List является Seq по умолчанию).

javaIterator.asScala.toIndexedSeq
8 голосов
/ 16 мая 2011

РЕДАКТИРОВАТЬ: Вероятно, вам следует взглянуть на Ответ Кевина Райта , который обеспечивает лучшее решение, доступное начиная с Scala 2.8.1, с меньшей неявной магией.


Вы можете импортировать неявные преобразования из scala.collection.JavaConversions, а затем без проблем создать новую коллекцию Scala, например, как это:

import collection.JavaConversions._
println(List() ++ javaIterator)

Ваш итератор Java преобразуется в итератор Scala JavaConversions.asScalaIterator. Итератор Scala с элементами типа A реализует TraversableOnce[A], который является типом аргумента, необходимого для объединения коллекций с ++.

Если вам нужен другой тип коллекции, просто измените List() на тот, который вам нужен (например, IndexedSeq() или collection.mutable.Seq() и т. Д.).

...