-2

I'm trying to call my Scala Util object from Java code:

Main.java

Set<Long> items = new HashSet<Long>();
// fill up items with Long
MyUtil.foo(100, items);

Util.scala

object Foo {
 type Id = Long
 def foo(id: Id, items: scala.collection.mutable.Set[Id]) 

Here's the compile-time error:

  could not parse error message:   
  required: long,scala.collection.mutable.Set<Object>
  found: Long,java.util.Set<Long>
  reason: actual argument java.util.Set<Long> cannot be converted to 
      scala.collection.mutable.Set<Object> by method invocation conversion`

From reading these Java to Scala Collections docs, I am using a mutable Set rather than the default, immutable Set:

scala.collection.mutable.Set <=> java.util.Set

But, I don't understand the error message. By using a Long (boxed long) in my Java code, why is a Set<Long> found?

2
  • Those conversion work as far as I understand while in .scala. Java can not cast from class A to B like that. Commented Jan 30, 2014 at 20:55
  • why the down-vote? is this problem really that simple? Commented Jan 31, 2014 at 15:11

2 Answers 2

2

Demonstrating what the commenter said:

scala> import collection.JavaConverters._
import collection.JavaConverters._

scala> val js = (1 to 10).toSet.asJava
js: java.util.Set[Int] = [5, 10, 1, 6, 9, 2, 7, 3, 8, 4]

scala> def f(is: collection.mutable.Set[Int]) = is.size
f: (is: scala.collection.mutable.Set[Int])Int

scala> def g(js: java.util.Set[Int]) = f(js.asScala)
g: (js: java.util.Set[Int])Int

scala> g(js)
res0: Int = 10
Sign up to request clarification or add additional context in comments.

3 Comments

Hi @som-snytt. Would error: value toSet is not a member of java.util.Set[Long] show up here: foo(items: java.util.Set[Long]) { val scalaSet = items.toSet } due to the java.util.Set type?
Yes. So the preferred idiom is to use JavaConverters (not Conversions), and call asJava and asScala to convert, as shown. Then in your method that takes a Java set, call asScala on it first. You could also call js.asScala.toSet to build an immutable Set.
I ran into another error that may or may not be related to this one - stackoverflow.com/questions/21483121/…. If you get time, please take a look. Thanks
1

Working with Scala collections and type aliases from Java code (not the converse, as som-snytt showed :) is going to be at least nasty, most likely very painful, and quite possibly impossible.

If you're able to modify the Scala side of the API, I'd recommend adding a Java-friendlier API to it. If not, I guess you could build an adapter layer in Scala that proxies Java clients through to the native Scala API.

So, something like:

// Original Scala
object Foo {
  type Id = Long
  def foo(id: Id, items: scala.collection.mutable.Set[Id]) 
}

// Java adapter -- generics might be made to work on the Java side, 
// but Long is particularly problematic, so we'll just force it here
object FooJ {
  import scala.collection.JavaConverters._

  def foo(id: Long, items: java.util.Set[Long]) = {
    Foo.foo(id, items.asScala)
  }
}

2 Comments

Thanks. Perhaps it's obvious, but ju.Set[Long] is an abbreviation for java.util.Set[Long]?
Whoops, yeah. Fixed. :)

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.