36

Is there a way in Scala to convert a List[Int] to java.util.List[java.lang.Integer]?

I'm interfacing with Java (Thrift).

JavaConversions supports List --> java.util.List, and implicits exist between Int --> java.lang.Integer, but from what I can tell I would still need an extra pass to manually do the conversion:

val y = List(1)     
val z: java.util.List[Integer] = asList(y)  map { (x: Int) => x : java.lang.Integer }

6 Answers 6

27

Apparently you need both conversions. However, you can group them in a single implicit conversion:

implicit def toIntegerList( lst: List[Int] ) =
  seqAsJavaList( lst.map( i => i:java.lang.Integer ) )

Example:

scala> def sizeOf( lst: java.util.List[java.lang.Integer] ) = lst.size

scala> sizeOf( List(1,2,3) )
res5: Int = 3
Sign up to request clarification or add additional context in comments.

Comments

25

Because the underlying representation of Int is Integer you can cast directly to java.util.List[java.lang.Integer]. It will save you an O(n) operation and some implicit stuff.

import collection.JavaConversions._

class A {
  def l() = asList(List(1,2)).asInstanceOf[java.util.List[java.lang.Integer]]
}

Then you can use from Java like this:

A a = new A();
java.util.List<Integer> l = a.l();

Note that on 2.9.0 ,I get a deprecation warning on asList (use seqAsJavaList instead)

1 Comment

This seems the most correct answer. Still relevant with scala.collection.convert.decorateAsJava as of 2014 with Scala 2.11.1.
4

Did you try:

val javalist = collection.JavaConversions.asJavaList (y)

I'm not sure, whether you need a conversion Int=>Integer or Int=>int here. Can you try it out?

Update: The times, they are a changing. Today you'll get a deprecated warning for that code. Use instead:

import scala.collection.JavaConverters._
val y = List (1)
> y: List[Int] = List(1)

val javalist = (y).asJava
> javalist: java.util.List[Int] = [1]

2 Comments

It appears it does not actually convert the underlying type, at least Idea gives me type errors.
I only get a warning today but it is still working - 2 years after answering: warning: there were 1 deprecation warnings; re-run with -deprecation for details javalist: java.util.List[Int] = [1]. Today you would use JavaConverters. I update my answer.
2

This doesn't have an implicit at the outmost layer, but I like this generic approach and have implemented it for a couple of types of collections (List, Map).

import java.util.{List => JList}
import scala.collection.JavaConverters._

  def scalaList2JavaList[A, B](scalaList: List[A])
                              (implicit a2bConversion: A => B): JList[B] =
    (scalaList map a2bConversion).asJava

Since an implicit conversion from Int to Integer is part of standard lib, usage in this case would just look like this:

  scalaList2JavaList[Int, Integer](someScalaList)

In the other direction!

(since I have these available anyway as they were my original implementations...)

import java.util.{List => JList}
import scala.collection.JavaConversions._

  def javaList2ScalaList[A, B](javaList: JList[A])
                              (implicit a2bConversion: A => B): List[B] =
    javaList.toList map a2bConversion

Usage:

  javaList2ScalaList[Integer, Int](someJavaList)

This can then be re-used for all lists so long as an implicit conversion of the contained type is in scope.

(And in case you're curious, here is my implementation for map...)

  def javaMap2ScalaMap[A, B, C, D](javaMap: util.Map[A, B])(implicit a2cConversion: A => C, b2dConversion: B => D): Map[C, D] =
    javaMap.toMap map { case (a, b) => (a2cConversion(a), b2dConversion(b)) }

Comments

1

Starting Scala 2.13, the standard library includes scala.jdk.CollectionConverters which provides Scala to Java implicit collection conversions.

Which we can combine with java.lang.Integer::valueOf to convert Scala's Int to Java's Integer:

import scala.jdk.CollectionConverters._

List(1, 2, 3).map(Integer.valueOf).asJava
// java.util.List[Integer] = [1, 2, 3]

Comments

0

I was trying to pass a Map[String, Double] to a Java method. But the problem was JavaConversions converts the Map to a java Map, but leaves the scala Double as is, instead of converting it to java.lang.Double. After a few hours of seaching I found [Alvaro Carrasco's answer])https://stackoverflow.com/a/40683561/1612432), it is as simple as doing:

val scalaMap = // Some Map[String, Double]
val javaMap = scalaMap.mapValues(Double.box)

After this, javaMap is a Map[String, java.lang.Double]. Then you can pass this to a java function that expects a Map<String, Double> and thanks to implicit conversions the Scala Map will be converted to java.util.Map

In your case would be the same, but with Int.box:

val y = List(1)
val javay = y.map(Int.box)

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.