The Artima Developer Community
Sponsored Link

Categorist's Notes
Practical Scala/Java interoperability by small examples
by Vlad Patryshev
November 9, 2010
Summary
While Scala can work with Java collections, and Java, more or less, can work with Scala collections, for sanity sake they better should be kept separate. So how do Java and Scala code exchange collections?

Advertisement

If you try to combine Java code with Scala in your application, everything seems to go fine until you bump into big differences between Java collections and Scala collections. A Scala Traversable is not Java Iterable and vice versa; maps are different, etc. So, in practice, you have to do conversion. Fortunately, there are pretty good implicit converters in Scala 2.8; what remains is to use them properly. I'll show a couple of pretty self-explaining examples here. Here our Scala code returns a Set to Java:

package com.company.user
 
import java.util.{Set => JavaSet}
import scala.collection.JavaConversions._
 
class GetAllGadgets(withHistory: Boolean) extends Getter[JavaSet[GadgetView]] {
 
  overide def execute = allGadgets map { g => g view withHistory }
}
process is declared in (a Java interface) as returning JavaSet; so an implicit conversion is applied to the set produced by mapping allGadgets using g => g.view(withHistory) transformation. Here's how a unittest may look like:
    final Gadget gadget = new Gadget("test gadget");
    GetAllGadgets query = new GetAllGadgets(true);
    Mockery mockery = new Mockery();
    final GadgetStorage storage = mockery.mock(GadgetStorage.class);
    query.setStorage(storage);
 
    mockery.checking(new Expectations() {{
      one(storage).allGadgets(); will(returnValue(Sets.newHashSet(gadget)));
    }});
 
    Set<GadgetView> result = query.exec();
    assertEquals(1, result.size());
    assertEquals("test gadget", result.iterator().next().getName());
In the following example, the Scala class takes a Java Iterable and returns a Java Set:
...
import scala.collection.mutable.{Set => MutableSet}
import java.util.{Set => JavaSet}
import scala.collection.JavaConversions._
 
class GetGadgets(val ids: java.lang.Iterable[Id[Gadget]]) extends Getter[JavaSet[GadgetView]] {
 
  def gadgets: MutableSet[Gadget] = repo.find(Gadget.ID, ids)
  override def exec = gadgets map { g => g view false }
}
What happens here: we explicitly show that we accept a Java Iterable, but all other conversions are implicit. First, storage.find(Gadget.ID, ids) is a Java code; it returns a Java Set. This set is implicitly transformed into scala.collection.mutable.Set, known in the code under an alias of MutableSet, for clarity. Then process transform the set into a set of views, same as in the previous example - and converts the result, implicitly, to java.util.Set, just because such is the signature of the method process. A Java programmer would probably complain about not having the result of process explicitly defined right here. Well... the language is Scala, not Java. Wind of change. In an unfortunate case when we need both Scala and Java collections, we will have to declare two methods, like in the example below:
import java.util.{Map => JavaMap}
import scala.collection.JavaConversions._
 
class EntityIdentity {...
  def allProperties: Map[String, String] =
    Map("shortName"   -> entityNameShortForm,
        "longName"    -> etityNameLongForm,
        "emailSuffix" -> emailSuffix,
        "domainName"  -> domainName)
 
  def allPropertiesForJava: JavaMap[String, String] = allProperties 
This may be a little bit awkward, but still writing code in Java is a temporary nuisance, right?

Talk Back!

Have an opinion? Be the first to post a comment about this weblog entry.

RSS Feed

If you'd like to be notified whenever Vlad Patryshev adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Vlad Patryshev was born in Russia, graduated from Leningrad University, majoring in Algebra; His studies combined practical programming with interests in category and topos theory. He spent 7 years at Borland, 3.5 years at Google, and is now at Telenav, investigating the brave new mobile world.

This weblog entry is Copyright © 2010 Vlad Patryshev. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use