Как преобразовать Перечисление в Seq/List в scala?
Я пишу сервлет, и мне нужно получить все параметры из запроса. Я обнаружил, что request.getParameterNames
возвращает a java.util.Enumeration
, поэтому мне нужно написать код как:
val names = request.getParameterNames
while(names.hasMoreElements) {
val name = names.nextElement
}
Я хочу знать, есть ли способ конвертировать Enumeration
в Seq/List
, тогда я могу использовать метод map
?
Ответы
Ответ 1
Вы можете создать его самостоятельно, как это
val nameIterator = Iterator.continually((names, names.nextElement)).takeWhile(_._1.hasMoreElements).map(_._2)
Iterator.continually
выполняет вызов по имени на (names, names.nextElement)
, который на каждом шаге возвращает исходное перечисление и следующий элемент. Условие остановки, конечно, находится в takeWhile
и потому, что нам не нужно проходить вокруг перечисления навсегда, мы map
только значения.
В качестве альтернативы вы можете создать обертку:
val nameIterator = new Iterator[SomeType] { def hasNext = names.hasMoreElements; def next = names.nextElement }
Или, наконец, и это встроенный метод и, вероятно, тот, который будет использоваться в этом случае:
val nameIterator = new scala.collection.JavaConversions.JEnumerationWrapper(names)
Использование Implicits:
У меня есть еще один. Если вы импортируете
import scala.collection.JavaConversions._
вы можете сделать это неявно (и вы также получите неявные преобразования для других наборов Java)
request.getParameterNames.map(println)
и он просто работает.
Ответ 2
Текущая лучшая практика (начиная с 2.8.1) заключается в использовании scala.collection.JavaConverters
Этот класс немного отличается от JavaConversions
тем, что преобразования не полностью автоматические, что дает вам больше контроля (это хорошо):
import collection.JavaConverters._
val names = ...
val nameIterator = names.asScala
Используя этот механизм, вы получите соответствующие и безопасные для типов преобразования для большинства типов коллекций с помощью методов asScala/asJava
.
Ответ 3
Я не согласен с какими-либо другими ответами, но мне пришлось добавить тип, чтобы его можно было компилировать в Scala 2.9.2 и Java 7.
import scala.collection.JavaConversions._
...
val names=request.getParameterNames.asInstanceOf[java.util.Enumeration[String]].toSet
Ответ 4
Комментарий к Debilski отвечает, что метод Iterator.continually ошибочен, потому что он пропускает последнюю запись. Здесь мой тест:
val list = new java.util.ArrayList[String]
list.add("hello")
list.add("world")
val en = java.util.Collections.enumeration(list)
val names = Iterator.continually((en, en.nextElement)).takeWhile(_._1.hasMoreElements).map(_._2)
.foreach { name => println("name=" + name) }
Выход
name=hello
Второй элемент (name = world) отсутствует!
Я получил это, чтобы работать, используя JavaConversions.enumerationAsSaalaIterator, как упоминалось другими.
Примечание. Мне не хватает комментариев, чтобы прокомментировать сообщение Debilski.