Converting a Java collection into a Scala collection
Asked Answered
K

10

90

Related to Stack Overflow question Scala equivalent of new HashSet(Collection) , how do I convert a Java collection (java.util.List say) into a Scala collection List?

I am actually trying to convert a Java API call to Spring's SimpleJdbcTemplate, which returns a java.util.List<T>, into a Scala immutable HashSet. So for example:

val l: java.util.List[String] = javaApi.query( ... )
val s: HashSet[String] = //make a set from l

This seems to work. Criticism is welcome!

import scala.collection.immutable.Set
import scala.collection.jcl.Buffer 
val s: scala.collection.Set[String] =
                      Set(Buffer(javaApi.query( ... ) ) : _ *)
Kismet answered 23/3, 2009 at 18:46 Comment(0)
V
16

Your last suggestion works, but you can also avoid using jcl.Buffer:

Set(javaApi.query(...).toArray: _*)

Note that scala.collection.immutable.Set is made available by default thanks to Predef.scala.

Virtuoso answered 24/3, 2009 at 7:51 Comment(1)
This suggestion doesn't work where I want to keep the type informationKismet
B
128

For future reference: With Scala 2.8, it could be done like this:

import scala.collection.JavaConversions._
val list = new java.util.ArrayList[String]()
list.add("test")
val set = list.toSet

set is a scala.collection.immutable.Set[String] after this.

Also see Ben James' answer for a more explicit way (using JavaConverters), which seems to be recommended now.

Bituminize answered 19/10, 2010 at 14:49 Comment(3)
Looks like now JavaConversions has some implicits making the toSet call not necessary.Brita
@Brita I think it's better if the conversion is explicit (see #8302447)Officiant
you are right, its better to use import scala.collection.JavaConverters._Cougar
C
62

If you want to be more explicit than the JavaConversions demonstrated in robinst's answer, you can use JavaConverters:

import scala.collection.JavaConverters._
val l = new java.util.ArrayList[java.lang.String]
val s = l.asScala.toSet
Cecilacecile answered 15/6, 2011 at 11:11 Comment(0)
L
25

JavaConversions (robinst's answer) and JavaConverters (Ben James's answer) have been deprecated with Scala 2.10.

Instead of JavaConversions use:

import scala.collection.convert.wrapAll._

as suggested by aleksandr_hramcov.

Instead of JavaConverters use:

import scala.collection.convert.decorateAll._

For both there is also the possibility to only import the conversions/converters to Java or Scala respectively, e.g.:

import scala.collection.convert.wrapAsScala._

Update: The statement above that JavaConversions and JavaConverters were deprecated seems to be wrong. There were some deprecated properties in Scala 2.10, which resulted in deprecation warnings when importing them. So the alternate imports here seem to be only aliases. Though I still prefer them, as IMHO the names are more appropriate.

Lignocellulose answered 18/8, 2014 at 8:52 Comment(2)
Why do you say the JavaConversions and JavaConverters are deprecated? In the current documentation 2.11.8 both are not marked as being deprecated and they also do not have a reference to 'decorateAll' or 'wrapAll' stating that is the new and preferred usage.Burrow
@JoostdenBoer Seems there were some deprecated decorators there in Scala 2.10, though they seem to have been removed again with Scala 2.11.Lignocellulose
V
16

Your last suggestion works, but you can also avoid using jcl.Buffer:

Set(javaApi.query(...).toArray: _*)

Note that scala.collection.immutable.Set is made available by default thanks to Predef.scala.

Virtuoso answered 24/3, 2009 at 7:51 Comment(1)
This suggestion doesn't work where I want to keep the type informationKismet
M
13

You may also want to explore this excellent library: scalaj-collection that has two-way conversion between Java and Scala collections. In your case, to convert a java.util.List to Scala List you can do this:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala
Mohandis answered 12/5, 2010 at 18:47 Comment(2)
That library is the greatest thing ever. Really really works well.Bharat
Revisiting this after couple of years, Scala's JavaConverters is the way to go.Mohandis
P
7

Starting Scala 2.13, package scala.jdk.CollectionConverters replaces packages scala.collection.JavaConverters/JavaConversions._:

import scala.jdk.CollectionConverters._

// val javaList: java.util.List[String] = java.util.Arrays.asList("one","two","three")
javaList.asScala
// collection.mutable.Buffer[String] = Buffer("one", "two", "three")
javaList.asScala.toSet
// collection.immutable.Set[String] = Set("one", "two", "three")
Paternoster answered 29/3, 2019 at 0:16 Comment(0)
C
3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])
Corrianne answered 8/10, 2010 at 7:26 Comment(1)
this is a great answer and solved my problem. Most of the methods mentioned on the internet just convert the (eg) java.util.List[java.lang.Long] to scala.collection.immutable.List[java.lang.Long]. So this method worked for me to convert it to scala.collection.immutable.List[scala.Long]Radium
Z
2

You can add the type information in the toArray call to make the Set be parameterized:

 val s = Set(javaApi.query(....).toArray(new Array[String](0)) : _*)

This might be preferable as the collections package is going through a major rework for Scala 2.8 and the scala.collection.jcl package is going away

Zalucki answered 23/3, 2010 at 19:43 Comment(0)
L
1

You could convert the Java collection to an array and then create a Scala list from that:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)
Lawley answered 23/3, 2009 at 18:50 Comment(1)
This isn't great because my java.util.List is coming back out of a Java API as a parametrized list (so my call to the API yields a java.util.List<String>) - I'm trying to turn this into a scala immutable HashSetKismet
C
1

Another simple way to solve this problem:

import collection.convert.wrapAll._
Castanets answered 7/3, 2014 at 5:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.