How to convert Enumeration to Seq/List in scala?
I'm writing a servlet, and need to get all parameters from the request. I found request.getParameterNames
returns a java.util.Enumeration
开发者_高级运维, so I have to write code as:
val names = request.getParameterNames
while(names.hasMoreElements) {
val name = names.nextElement
}
I wanna know is there any way to convert a Enumeration
to a Seq/List
, then I can use the map
method?
Use JavaConverters
See https://stackoverflow.com/a/5184386/133106
Use a wrapper Iterator
You could build up a wrapper:
val nameIterator = new Iterator[SomeType] { def hasNext = names.hasMoreElements; def next = names.nextElement }
Use JavaConversions wrapper
val nameIterator = new scala.collection.JavaConversions.JEnumerationWrapper(names)
Using JavaConversions implicits
If you import
import scala.collection.JavaConversions._
you can do it implicitly (and you’ll also get implicit conversions for other Java collecitons)
request.getParameterNames.map(println)
Use Iterator.continually
You might be tempted to build an iterator using Iterator.continually
like an earlier version of this answer proposed:
val nameIterator = Iterator.continually((names, names.nextElement)).takeWhile(_._1.hasMoreElements).map(_._2)
but it's incorrect as the last element of the enumerator will be discarded.
The reason is that the hasMoreElement
call in the takeWhile
is executed after calling nextElement
in the continually
, thus discarding the last value.
Current best practice (since 2.8.1) is to use scala.collection.JavaConverters
- Scaladoc here
This class differs from JavaConversions
slightly, in that the conversions are not fully automatic, giving you more control (this is a good thing):
import collection.JavaConverters._
val names = ...
val nameIterator = names.asScala
Using this mechanism, you'll get appropriate and type-safe conversions for most collection types via the asScala/asJava
methods.
I don't disagree with any of the other answers but I had to add a type cast to get this to compile in Scala 2.9.2 and Java 7.
import scala.collection.JavaConversions._
...
val names=request.getParameterNames.asInstanceOf[java.util.Enumeration[String]].toSet
A comment on Debilski's answer that the Iterator.continually approach is wrong because it misses the last entry. Here's my test:
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) }
Output is
name=hello
The second item (name=world) is missing!
I got this to work by using JavaConversions.enumerationAsScalaIterator as mentioned by others.
Note I don't have enough rep to comment on Debilski's post directly.
精彩评论