与 Scala 一样,Java 也有一个丰富的集合库。两者之间有许多相似之处。例如,这两个库都了解迭代器、可迭代对象、集合、映射和序列。但也有重要的区别。特别是,Scala 库更强调不可变集合,并提供了更多将集合转换为新集合的操作。
有时你可能需要从一个集合框架传递到另一个集合框架。例如,你可能希望访问现有的 Java 集合,就好像它是 Scala 集合一样。或者你可能希望将 Scala 的一个集合传递给 Java 方法,该方法需要其 Java 对应项。这样做非常容易,因为 Scala 在 CollectionConverters 对象中提供了所有主要集合类型之间的隐式转换。特别是,你会发现以下类型之间的双向转换。
Iterator <=> java.util.Iterator
Iterator <=> java.util.Enumeration
Iterable <=> java.lang.Iterable
Iterable <=> java.util.Collection
mutable.Buffer <=> java.util.List
mutable.Set <=> java.util.Set
mutable.Map <=> java.util.Map
mutable.ConcurrentMap <=> java.util.concurrent.ConcurrentMap
要启用这些转换,请从 CollectionConverters 对象导入它们
scala> import scala.jdk.CollectionConverters._
import scala.jdk.CollectionConverters._
scala> import scala.jdk.CollectionConverters.*
import scala.jdk.CollectionConverters.*
这通过称为 asScala
和 asJava
的扩展方法,实现了 Scala 集合与其对应的 Java 集合之间的转换
scala> import collection.mutable._
import collection.mutable._
scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava
val jul: java.util.List[Int] = [1, 2, 3]
scala> val buf: Seq[Int] = jul.asScala
val buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3)
scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava
val m: java.util.Map[String,Int] = {abc=1, hello=2}
scala> import collection.mutable.*
import collection.mutable.*
scala> val jul: java.util.List[Int] = ArrayBuffer(1, 2, 3).asJava
val jul: java.util.List[Int] = [1, 2, 3]
scala> val buf: Seq[Int] = jul.asScala
val buf: scala.collection.mutable.Seq[Int] = ArrayBuffer(1, 2, 3)
scala> val m: java.util.Map[String, Int] = HashMap("abc" -> 1, "hello" -> 2).asJava
val m: java.util.Map[String,Int] = {abc=1, hello=2}
在内部,这些转换通过设置一个“包装器”对象来工作,该对象将所有操作转发到底层集合对象。因此,在 Java 和 Scala 之间转换时,集合永远不会被复制。一个有趣的特性是,如果你对一个 Java 类型进行往返转换,将其转换为对应的 Scala 类型,然后再转换回相同的 Java 类型,你最终将得到与你开始时相同的集合对象。
某些其他 Scala 集合也可以转换为 Java,但不能转换回原始的 Scala 类型
Seq => java.util.List
mutable.Seq => java.util.List
Set => java.util.Set
Map => java.util.Map
由于 Java 在其类型中不区分可变和不可变集合,因此从 scala.immutable.List
这样的类型进行转换将产生一个 java.util.List
,其中所有变异操作都会抛出“UnsupportedOperationException”。这是一个示例
scala> val jul = List(1, 2, 3).asJava
val jul: java.util.List[Int] = [1, 2, 3]
scala> jul.add(7)
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)