views:

159

answers:

3

In my Scala function, i'm traversing a Java ArrayCollection, extracting specific elements which should form a new collection. At the end, it has to be a Java-ArrayList again, because i'm interacting with a Java Framework. My Code:

// to make scala-style iterating over arraylist possible
import scala.collection.JavaConversions._

// ArrayList contains elements of this type:
class Subscription(val subscriber:User, val sender:User)

// I'm getting this list from Java:
val jArrayList = new ArrayList[Subscription]
// Buffer:scala.collection.mutable.Buffer[User]
val buffer = for (val subscription <- jArrayList ) yield subscription.sender

How can i convert the Buffer to an ArrayList[User]? Or shouldn't i use yield here?

+1  A: 

You could pass the buffer in the ArrayList constructor to create a new java ArrayList:

var newArray = new ArrayList[Int] (buffer)
onof
This would probably work due to the fact that it will be converted implicitly to a java.util.List. Good stuff, although sometimes you really don't need an ArrayList rather than just a List.
Calum
+1  A: 

When one uses for comprehensions, the underlying code uses map, flatMap, foreach, filter or withFilter -- see related questions. In this particular example, that code would be equivalent to jArrayList.map(_.sender), and map produces new collections (I'm ignoring the implicit conversion here to keep it simple).

What happens here that is perhaps unintuitive, and perhaps could be improved on, is that ArrayList does not implement map. The implicit conversion gives you a Buffer instead, and a map on a Buffer returns a Buffer.

Granted, the Buffer on JavaConversions preserves the underlying collection, the ArrayList, as the backing store. The newly created Buffer, on the other hand, won't be based on that, but on one of Scala's own collections.

You could always do this, though:

val buffer = (for (val subscription <- jArrayList ) yield subscription.sender).asList
Daniel
+3  A: 

You should be able to convert it back by specifying what type you'd like buffer to be (JavaConversions should be brought into play automatically when the type you're trying to get and the one you have are incompatible):

val buffer: java.util.List[User] =
  for (val subscription <- jArrayList ) yield subscription.sender

Alternatively you can call the conversion from JavaConversions explicitly if you want to make it clear what you're doing:

val buffer = asList( for ( ... ) ) // buffer should have type "java.util.List[User]"

Neither of these actually produce an ArrayList; rather, they create a generic List, but it's generally bad practice to specify collection types directly. If you must have an ArrayList, pass your List to the constructor of ArrayList which takes a Collection:

new ArrayList( buffer )
Calum