26

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?

4 Answers 4

33

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.

Sign up to request clarification or add additional context in comments.

2 Comments

I think the first code contains a bug: it doesn't return the very last element. To get it you should do something like val nameIterator = Iterator.continually((names.hasMoreElements, names)).takeWhile(_._1).map(_._2.nextElement)
Note that JavaConversions is deprecated. See Kevin Wright's answer.
32

Current best practice (since 2.8.1) is to use scala.collection.JavaConverters

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.

4 Comments

asScala didn't work for me for some reason. I used enumerationAsScalaIterator(enumeration).
@Mygod did you do the import? You need it in order to get the implicits.
Looks to now need import scala.collection.JavaConverters._
scala.collection.JavaConverters$' is deprecated Symbol JavaConverters is deprecated. Use scala.jdk.CollectionConverters instead
1

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

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.