kmizuの日記

プログラミングや形式言語に関係のあることを書いたり書かなかったり。

ScalaのコレクションからJavaのコレクションへの変換用ライブラリ

Scala勉強会のときに、誰かから、ScalaのコレクションをJavaのコレクションに変換するためのライブラリって無いの?という質問があって、それに対して、そういうものは無いけど、割とすぐ書けますよ、てな感じで答えたのをふと思い出して、サクっと書いてみた(Scala-sandboxにも既に同様のコードを置いてあるけど、ちょっと違う)。

package example
import java.util
object ToJavaCollection {
  class ToJavaListOrSet[A](it :Iterable[A]){
    def toJavaList :util.List[A] = {
      it.foldLeft(new util.ArrayList[A]){(list, e) => list.add(e); list}
    }
    def toJavaSet :util.Set[A] = {
      it.foldLeft(new util.HashSet[A]){(set, e) => set.add(e); set}
    }
  }
  class ToJavaMap[A, B](it :Iterable[(A, B)]) {
    def toJavaMap :util.Map[A, B] = {
      it.foldLeft(new util.HashMap[A, B]){(map, e) => 
        map.put(e._1, e._2); map
      }
    }
  }
  implicit def toJavaListOrSet[A](it :Iterable[A]) =
    new ToJavaListOrSet[A](it)
  implicit def toJavaMap[A, B](it :Iterable[(A, B)]) =
    new ToJavaMap[A, B](it)
}

使う側のコードはこんな感じ。

import example.ToJavaCollection._
val javaList = List(1, 2, 3).toJavaList
val javaSet = Set(1, 2, 3).toJavaSet
val javaMap = Map("A" -> 1, "B" -> 2, "C" -> 3).toJavaMap
println(javaList + ":" + javaList.getClass)
println(javaSet + ":" + javaSet.getClass)
println(javaMap + ":" + javaMap.getClass)

実行結果:

[1, 2, 3]:class java.util.ArrayList
[1, 2, 3]:class java.util.HashSet
{A=1, B=2, C=3}:class java.util.HashMap

これだと、変換元のScalaのコレクションの要素数が多い場合、コピーのコストが高くつく可能性があるが、それが問題になる場合は、scala.collection.jclパッケージの逆アプローチで、ScalaのコレクションをJavaのコレクションに見せかけるラッパーがあると良いかも。