2.7からの移行トップコレクションをゼロから作成するJavaとScalaのコレクションの変換目次

JavaとScalaのコレクションの変換

ScalaのようにJavaも豊かなコレクションライブラリを備えています。 両者の間には多くの類似点があります。 例えば、両方のライブラリはイテレータ・イテラブル・集合・マップ・列を理解します。 しかし重要な違いもあります。 特に、Scalaライブラリは不変なコレクションをより重要視し、コレクションを新しいものへ変換する演算をより多く提供します。

片方のコレクションフレームワークからもう片方へ移動する必要がある場合があります。 例えば既存のJavaのコレクションを、あたかもScalaのコレクションであったかのようにアクセスしたいこともあります。 もしくはJavaの対応物を期待するJavaメソッドにScalaのコレクションを渡したいこともあります。 Scalaは主要なコレクション型間の暗黙の変換をJavaConversionsオブジェクトで提供しているため、これはとても簡単です。 特に、以下の型については双方向変換があるのに気付くでしょう。

Iteratorjava.util.Iterator
Iteratorjava.util.Enumeration
Iterablejava.lang.Iterable
Iterablejava.util.Collection
mutable.Bufferjava.util.List
mutable.Setjava.util.Set
mutable.Mapjava.util.Map
mutable.ConcurrentMapjava.util.concurrent.ConcurrentMap

これらの変換を有効にするためには、単にJavaConversionsからメソッドをインポートします:

scala> import collection.JavaConversions._
import collection.JavaConversions._

これでScalaコレクションと対応するJavaのコレクション間での自動変換が手に入りました。

scala> import collection.mutable._
import collection.mutable._
scala> val jul: java.util.List[Int] = ArrayBuffer(123)
jul: java.util.List[Int] = [1, 2, 3]
scala> val buf: Seq[Int] = jul
buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3)
scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1"hello" -> 2)
m: java.util.Map[String,Int] = {hello=2, abc=1}

内部的にはこれらの変換は全ての演算を元となるコレクションオブジェクトに転送する「ラッパー」オブジェクトの作成により動作します。 そのためJavaとScala間で変換する際にコレクションは決してコピーされません。 おもしろい性質として、もし往復変換(例えばJavaの型から対応するScalaの型に変換して同じJavaの型に戻す)した場合、最初のコレクションオブジェクトと全く同一のものとなる点が挙げられます。

他にも良く使われるScalaのコレクションでJavaの型に変換できるものがありますが、逆の変換を備えてはいません。 以下のものがそうです。

Seqjava.util.List
mutable.Seqjava.utl.List
Setjava.util.Set
Mapjava.util.Map

Javaでは可変と不変なコレクションを型で区別しませんので、例えばscala.immutable.Listjava.util.Listになったとすると、変異させる演算は全て“UnsupportedOperationException”を投げます。 これはその例です:

scala> jul = List(123)
jul: java.util.List[Int] = [123]
scala> jul.add(7)
java.lang.UnsupportedOperationException
        at java.util.AbstractList.add(AbstractList.java:131)

続いては: 2.7からの移行


2.7からの移行トップコレクションをゼロから作成するJavaとScalaのコレクションの変換目次