scala JavaConverters原理用法示例源码详解
文章目录
原理
JavaConverters
对象提供了一组装饰器类和方法,用于在Scala集合和Java集合之间进行转换。它的原理是利用隐式转换(Implicit Conversion)和隐式类(Implicit Class)来实现。
在JavaConverters
对象中,定义了多个隐式转换方法,这些方法会被自动应用于需要进行集合转换的地方。这些隐式转换方法接受一个源类型的集合对象,并返回一个装饰器对象,该装饰器对象包含了相应的转换方法,用于将源类型的集合转换为目标类型的集合。
例如,asJavaIteratorConverter
方法是一个隐式转换方法,它接受一个scala.collection.Iterator
类型的对象,并返回一个AsJava[java.util.Iterator]
类型的装饰器对象。通过这个装饰器对象,可以调用asJava
方法将Scala的迭代器转换为Java的迭代器。
同时,JavaConverters
对象还使用了隐式类(Implicit Class)。隐式类是在Scala 2.10版本引入的特性,它允许在类的定义周围包裹隐式转换方法。通过定义隐式类,可以为指定的类型添加额外的方法,而无需显式地调用转换方法。
在JavaConverters
对象中,通过定义隐式类RichIterable
、RichIterator
、RichBuffer
、RichSet
、RichMap
等,为Scala集合类型添加了一些额外的方法。这些方法可以方便地进行Java和Scala集合之间的转换。
当需要将Scala集合转换为Java集合时,可以使用asJava
方法调用适当的装饰器对象,实现类型的转换。类似地,当需要将Java集合转换为Scala集合时,可以使用asScala
方法调用适当的装饰器对象。
通过隐式转换和隐式类的机制,JavaConverters
对象提供了一种简洁而方便的方式,在Scala和Java集合之间进行双向的转换操作。
示例
object JavaConvertTest extends App{
import scala.collection.JavaConverters._
// 将Java List转换为Scala List
val javaList: java.util.List[Int] = java.util.Arrays.asList(1, 2, 3, 4, 5)
val scalaList: List[Int] = javaList.asScala.toList
println(s"Scala List: $scalaList") // 输出:Scala List: List(1, 2, 3, 4, 5)
// 将Java Set转换为Scala Set
val javaSet: java.util.Set[String] = new java.util.HashSet[String]()
javaSet.add("John")
javaSet.add("Jane")
val scalaSet: Set[String] = javaSet.asScala.toSet
println(s"Scala Set: $scalaSet") // 输出:Scala Set: Set(John, Jane)
// 将Java Map转换为Scala Map
val javaMap: java.util.Map[String, Int] = new java.util.HashMap[String, Int]()
javaMap.put("Alice", 25)
javaMap.put("Bob", 30)
val scalaMap: Map[String, Int] = javaMap.asScala.toMap
println(s"Scala Map: $scalaMap") // 输出:Scala Map: Map(Alice -> 25, Bob -> 30)
// 将Scala List转换为Java List
val scalaList2: List[String] = List("John", "Jane")
val javaList2: java.util.List[String] = scalaList2.asJava
println(s"Java List: $javaList2") // 输出:Java List: [John, Jane]
// 将Scala Set转换为Java Set
val scalaSet2: Set[Double] = Set(1.5, 2.5, 3.5)
val javaSet2: java.util.Set[Double] = scalaSet2.asJava
println(s"Java Set: $javaSet2") // 输出:Java Set: [1.5, 2.5, 3.5]
// 将Scala Map转换为Java Map
val scalaMap2: Map[String, Boolean] = Map("Alice" -> true, "Bob" -> false)
val javaMap2: java.util.Map[String, Boolean] = scalaMap2.asJava
println(s"Java Map: $javaMap2") // 输出:Java Map: {Alice=true, Bob=false}
}
源码分析
以上源码定义了一个JavaConverters
对象,其中包含了一组装饰器类和方法,用于在Scala集合和Java集合之间进行转换。
这些转换通过asJava
和asScala
方法实现:
scala.collection.Iterable
<=>java.lang.Iterable
scala.collection.Iterator
<=>java.util.Iterator
scala.collection.mutable.Buffer
<=>java.util.List
scala.collection.mutable.Set
<=>java.util.Set
scala.collection.mutable.Map
<=>java.util.Map
scala.collection.mutable.concurrent.Map
<=>java.util.concurrent.ConcurrentMap
在所有情况下,从源类型到目标类型的转换再返回原始源对象。例如:
import scala.collection.JavaConverters._
val sl = new scala.collection.mutable.ListBuffer[Int]
val jl: java.util.List[Int] = sl.asJava
val sl2: scala.collection.mutable.Buffer[Int] = jl.asScala
assert(sl eq sl2)
还支持以下转换,但是从Scala到Java的方向是通过更具体名称的方法实现的:asJavaCollection
、asJavaEnumeration
、asJavaDictionary
:
scala.collection.Iterable
<=>java.util.Collection
scala.collection.Iterator
<=>java.util.Enumeration
scala.collection.mutable.Map
<=>java.util.Dictionary
此外,还通过asJava
提供了以下单向转换:
scala.collection.Seq
=>java.util.List
scala.collection.mutable.Seq
=>java.util.List
scala.collection.Set
=>java.util.Set
scala.collection.Map
=>java.util.Map
该对象继承了DecorateAsJava
和DecorateAsScala
trait,提供了对这些装饰器类和方法的访问。通过使用JavaConverters
对象,我们可以方便地在Scala集合和Java集合之间进行转换。
中文源码
JavaConverters
package scala
package collection
import convert._
/** 一组装饰器,允许使用 `asScala` 和 `asJava` 方法在 Scala 和 Java 集合之间进行转换。
*
* 以下转换支持通过 `asJava`、`asScala` 进行:
*
* - `scala.collection.Iterable` <=> `java.lang.Iterable`
* - `scala.collection.Iterator` <=> `java.util.Iterator`
* - `scala.collection.mutable.Buffer` <=> `java.util.List`
* - `scala.collection.mutable.Set` <=> `java.util.Set`
* - `scala.collection.mutable.Map` <=> `java.util.Map`
* - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap`
*
* 在所有情况下,从源类型到目标类型再返回原始源对象,例如:
* {{{
* import scala.collection.JavaConverters._
*
* val sl = new scala.collection.mutable.ListBuffer[Int]
* val jl : java.util.List[Int] = sl.asJava
* val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
* assert(sl eq sl2)
* }}}
*
* 还支持以下转换,但是从 Scala 到 Java 的方向是由更具体命名的方法完成的:`asJavaCollection`、`asJavaEnumeration`、`asJavaDictionary`。
*
* - `scala.collection.Iterable` <=> `java.util.Collection`
* - `scala.collection.Iterator` <=> `java.util.Enumeration`
* - `scala.collection.mutable.Map` <=> `java.util.Dictionary`
*
* 此外,还通过 `asJava` 提供了以下单向转换:
*
* - `scala.collection.Seq` => `java.util.List`
* - `scala.collection.mutable.Seq` => `java.util.List`
* - `scala.collection.Set` => `java.util.Set`
* - `scala.collection.Map` => `java.util.Map`
*
* 作者:Martin Odersky
* 自版本:2.8.1
*/
object JavaConverters extends DecorateAsJava with DecorateAsScala
DecorateAsJava
/**
* 一个装饰器集合,允许使用`asScala`和`asJava`方法在Scala和Java集合之间进行转换。
*
* 支持以下转换通过`asJava`、`asScala`方法:
*
* - `scala.collection.Iterable` <=> `java.lang.Iterable`
* - `scala.collection.Iterator` <=> `java.util.Iterator`
* - `scala.collection.mutable.Buffer` <=> `java.util.List`
* - `scala.collection.mutable.Set` <=> `java.util.Set`
* - `scala.collection.mutable.Map` <=> `java.util.Map`
* - `scala.collection.mutable.concurrent.Map` <=> `java.util.concurrent.ConcurrentMap`
*
* 在所有情况下,从源类型到目标类型的转换再返回原始源对象,例如:
* {{{
* import scala.collection.JavaConverters._
*
* val sl = new scala.collection.mutable.ListBuffer[Int]
* val jl : java.util.List[Int] = sl.asJava
* val sl2 : scala.collection.mutable.Buffer[Int] = jl.asScala
* assert(sl eq sl2)
* }}}
*
* 还支持以下转换,但是方向 Scala 到 Java 是通过更具体命名的方法完成的:
* `asJavaCollection`、`asJavaEnumeration`、`asJavaDictionary`。
*
* - `scala.collection.Iterable` <=> `java.util.Collection`
* - `scala.collection.Iterator` <=> `java.util.Enumeration`
* - `scala.collection.mutable.Map` <=> `java.util.Dictionary`
*
* 此外,还提供了以下单向转换通过`asJava`实现:
*
* - `scala.collection.Seq` => `java.util.List`
* - `scala.collection.mutable.Seq` => `java.util.List`
* - `scala.collection.Set` => `java.util.Set`
* - `scala.collection.Map` => `java.util.Map`
*
* 作者:Martin Odersky
* 自2.8.1版本以来
*/
trait DecorateAsJava {
/**
* 添加一个`asJava`方法,它隐式地将Scala的`Iterator`转换为Java的`Iterator`。
* 返回的Java `Iterator`由提供的Scala `Iterator`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala `Iterator`先前是通过`asIterator(java.util.Iterator)`的隐式或显式调用获得的,
* 那么`asJava`方法将返回原始的Java `Iterator`。
*
* @param i 要转换的`Iterator`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `Iterator`视图。
*/
implicit def asJavaIteratorConverter[A](i: Iterator[A]): AsJava[ju.Iterator[A]] =
new AsJava(asJavaIterator(i))
/**
* 添加一个`asJavaEnumeration`方法,它隐式地将Scala的`Iterator`转换为Java的`Enumeration`。
* 返回的Java `Enumeration`由提供的Scala `Iterator`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala `Iterator`先前是通过`asIterator(java.util.Enumeration)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Enumeration`。
*
* @param i 要转换的`Iterator`。
* @return 具有`asJavaEnumeration`方法的对象,该方法返回参数的Java `Enumeration`视图。
*/
implicit def asJavaEnumerationConverter[A](i: Iterator[A]): AsJavaEnumeration[A] =
new AsJavaEnumeration(i)
/**
* 添加一个`asJava`方法,它隐式地将Scala的`Iterable`转换为Java的`Iterable`。
* 返回的Java `Iterable`由提供的Scala `Iterable`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala `Iterable`先前是通过`asIterable(java.lang.Iterable)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Iterable`。
*
* @param i 要转换的`Iterable`。
* @return 具有`asJavaCollection`方法的对象,该方法返回参数的Java `Iterable`视图。
*/
implicit def asJavaIterableConverter[A](i: Iterable[A]): AsJava[jl.Iterable[A]] =
new AsJava(asJavaIterable(i))
/**
* 添加一个`asJavaCollection`方法,它隐式地将Scala的`Iterable`转换为不可变的Java `Collection`。
* 如果Scala `Iterable`先前是通过`asSizedIterable(java.util.Collection)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Collection`。
*
* @param i 要转换的`SizedIterable`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `Collection`视图。
*/
implicit def asJavaCollectionConverter[A](i: Iterable[A]): AsJavaCollection[A] =
new AsJavaCollection(i)
/**
* 添加一个`asJava`方法,它隐式地将Scala的可变`Buffer`转换为Java的`List`。
* 返回的Java `List`由提供的Scala `Buffer`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Buffer`先前是通过`asBuffer(java.util.List)`的隐式或显式调用获得的,
* 那么将返回原始的Java `List`。
*
* @param b 要转换的`Buffer`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `List`视图。
*/
implicit def bufferAsJavaListConverter[A](b: mutable.Buffer[A]): AsJava[ju.List[A]] =
new AsJava(bufferAsJavaList(b))
/**
* 添加一个`asJava`方法,它隐式地将Scala的可变`Seq`转换为Java的`List`。
* 返回的Java `List`由提供的Scala `Seq`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Seq`先前是通过`asSeq(java.util.List)`的隐式或显式调用获得的,
* 那么将返回原始的Java `List`。
*
* @param b 要转换的`Seq`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `List`视图。
*/
implicit def mutableSeqAsJavaListConverter[A](b: mutable.Seq[A]): AsJava[ju.List[A]] =
new AsJava(mutableSeqAsJavaList(b))
/**
* 添加一个`asJava`方法,它隐式地将Scala的`Seq`转换为Java的`List`。
* 返回的Java `List`由提供的Scala `Seq`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Seq`先前是通过`asSeq(java.util.List)`的隐式或显式调用获得的,
* 那么将返回原始的Java `List`。
*
* @param b 要转换的`Seq`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `List`视图。
*/
implicit def seqAsJavaListConverter[A](b: Seq[A]): AsJava[ju.List[A]] =
new AsJava(seqAsJavaList(b))
/**
* 添加一个`asJava`方法,它隐式地将Scala的可变`Set`转换为Java的`Set`。
* 返回的Java `Set`由提供的Scala `Set`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Set`先前是通过`asSet(java.util.Set)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Set`。
*
* @param s 要转换的`Set`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `Set`视图。
*/
implicit def mutableSetAsJavaSetConverter[A](s: mutable.Set[A]): AsJava[ju.Set[A]] =
new AsJava(mutableSetAsJavaSet(s))
/**
* 添加一个`asJava`方法,它隐式地将Scala的`Set`转换为Java的`Set`。
* 返回的Java `Set`由提供的Scala `Set`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Set`先前是通过`asSet(java.util.Set)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Set`。
*
* @param s 要转换的`Set`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `Set`视图。
*/
implicit def setAsJavaSetConverter[A](s: Set[A]): AsJava[ju.Set[A]] =
new AsJava(setAsJavaSet(s))
/**
* 添加一个`asJava`方法,它隐式地将Scala的可变`Map`转换为Java的`Map`。
* 返回的Java `Map`由提供的Scala `Map`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Map`先前是通过`asMap(java.util.Map)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Map`。
*
* @param m 要转换的`Map`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `Map`视图。
*/
implicit def mutableMapAsJavaMapConverter[A, B](m: mutable.Map[A, B]): AsJava[ju.Map[A, B]] =
new AsJava(mutableMapAsJavaMap(m))
/**
* 添加一个`asJavaDictionary`方法,它隐式地将Scala的可变`Map`转换为Java的`Dictionary`。
* 返回的Java `Dictionary`由提供的Scala `Dictionary`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Dictionary`先前是通过`asMap(java.util.Dictionary)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Dictionary`。
*
* @param m 要转换的`Map`。
* @return 具有`asJavaDictionary`方法的对象,该方法返回参数的Java `Dictionary`视图。
*/
implicit def asJavaDictionaryConverter[A, B](m: mutable.Map[A, B]): AsJavaDictionary[A, B] =
new AsJavaDictionary(m)
/**
* 添加一个`asJava`方法,它隐式地将Scala的`Map`转换为Java的`Map`。
* 返回的Java `Map`由提供的Scala `Map`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`Map`先前是通过`asMap(java.util.Map)`的隐式或显式调用获得的,
* 那么将返回原始的Java `Map`。
*
* @param m 要转换的`Map`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `Map`视图。
*/
implicit def mapAsJavaMapConverter[A, B](m: Map[A, B]): AsJava[ju.Map[A, B]] =
new AsJava(mapAsJavaMap(m))
/**
* 添加一个`asJava`方法,它隐式地将Scala的可变`concurrent.Map`转换为Java的`ConcurrentMap`。
* 返回的Java `ConcurrentMap`由提供的Scala `concurrent.Map`支持,通过Java接口使用它的任何副作用都会通过Scala接口可见,反之亦然。
*
* 如果Scala的`concurrent.Map`先前是通过`asConcurrentMap(java.util.concurrent.ConcurrentMap)`的隐式或显式调用获得的,
* 那么将返回原始的Java `ConcurrentMap`。
*
* @param m 要转换的Scala `concurrent.Map`。
* @return 具有`asJava`方法的对象,该方法返回参数的Java `ConcurrentMap`视图。
*/
implicit def mapAsJavaConcurrentMapConverter[A, B](m: concurrent.Map[A, B]): AsJava[juc.ConcurrentMap[A, B]] =
new AsJava(mapAsJavaConcurrentMap(m))
}
这段代码是Scala标准库中的一个trait,提供了一些装饰器方法,用于在Scala集合和Java集合之间进行转换。
这个trait定义了一系列隐式转换方法,例如asJavaIteratorConverter
、asJavaEnumerationConverter
、asJavaIterableConverter
等等。这些方法允许在Scala集合和对应的Java集合之间相互转换,以便在使用时能够无缝切换。
该trait还提供了一些单向转换方法,例如mutableSeqAsJavaListConverter
、seqAsJavaListConverter
、mutableSetAsJavaSetConverter
等等,用于将特定类型的Scala集合转换为对应的Java集合。
DecorateAsScala
trait DecorateAsScala {
/**
* 添加一个`asScala`方法,它隐式地将Java的`Iterator`转换为Scala的`Iterator`。
*
* 返回的Scala `Iterator`由提供的Java `Iterator`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java `Iterator`先前是通过`asIterator(scala.collection.Iterator)`的隐式或显式调用获得的,
* 那么`asScala`方法将返回原始的Scala `Iterator`。
*
* @param i 要转换的`Iterator`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala `Iterator`视图。
*/
implicit def asScalaIteratorConverter[A](i : ju.Iterator[A]): AsScala[Iterator[A]] =
new AsScala(asScalaIterator(i))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Enumeration`转换为Scala的`Iterator`。
*
* 返回的Scala `Iterator`由提供的Java `Enumeration`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java `Enumeration`先前是通过`asEnumeration(scala.collection.Iterator)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `Iterator`。
*
* @param i 要转换的`Enumeration`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala `Iterator`视图。
*/
implicit def enumerationAsScalaIteratorConverter[A](i : ju.Enumeration[A]): AsScala[Iterator[A]] =
new AsScala(enumerationAsScalaIterator(i))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Iterable`转换为Scala的`Iterable`。
*
* 返回的Scala `Iterable`由提供的Java `Iterable`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java `Iterable`先前是通过`asIterable(scala.collection.Iterable)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `Iterable`。
*
* @param i 要转换的`Iterable`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala `Iterable`视图。
*/
implicit def iterableAsScalaIterableConverter[A](i : jl.Iterable[A]): AsScala[Iterable[A]] =
new AsScala(iterableAsScalaIterable(i))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Collection`转换为Scala的`Iterable`。
*
* 如果Java `Collection`先前是通过`asCollection(scala.collection.SizedIterable)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `SizedIterable`。
*
* @param i 要转换的`Collection`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala `SizedIterable`视图。
*/
implicit def collectionAsScalaIterableConverter[A](i : ju.Collection[A]): AsScala[Iterable[A]] =
new AsScala(collectionAsScalaIterable(i))
/**
* 添加一个`asScala`方法,它隐式地将Java的`List`转换为Scala的可变`Buffer`。
*
* 返回的Scala `Buffer`由提供的Java `List`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java的`List`先前是通过`asList(scala.collection.mutable.Buffer)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `Buffer`。
*
* @param l 要转换的`List`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala可变`Buffer`视图。
*/
implicit def asScalaBufferConverter[A](l : ju.List[A]): AsScala[mutable.Buffer[A]] =
new AsScala(asScalaBuffer(l))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Set`转换为Scala的可变`Set`。
*
* 返回的Scala `Set`由提供的Java `Set`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java的`Set`先前是通过`asSet(scala.collection.mutable.Set)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `Set`。
*
* @param s 要转换的`Set`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala可变`Set`视图。
*/
implicit def asScalaSetConverter[A](s : ju.Set[A]): AsScala[mutable.Set[A]] =
new AsScala(asScalaSet(s))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Map`转换为Scala的可变`Map`。
* 返回的Scala `Map`由提供的Java `Map`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java的`Map`先前是通过`asMap(scala.collection.mutable.Map)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `Map`。
*
* 如果包装的map是同步的(例如从`java.util.Collections.synchronizedMap`),则您需要在所有非原子操作周围使用`underlying.synchronized`进行包装。
* 这包括`get`,因为`java.util.Map`的API不允许在可能存在`null`值时进行原子`get`。
*
* @param m 要转换的`Map`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala可变`Map`视图。
*/
implicit def mapAsScalaMapConverter[A, B](m : ju.Map[A, B]): AsScala[mutable.Map[A, B]] =
new AsScala(mapAsScalaMap(m))
/**
* 添加一个`asScala`方法,它隐式地将Java的`ConcurrentMap`转换为Scala的可变`concurrent.Map`。
* 返回的Scala `concurrent.Map`由提供的Java `ConcurrentMap`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* 如果Java的`ConcurrentMap`先前是通过`mapAsScalaConcurrentMap(scala.collection.mutable.ConcurrentMap)`的隐式或显式调用获得的,
* 那么将返回原始的Scala `concurrent.Map`。
*
* @param m 要转换的`ConcurrentMap`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala可变`concurrent.Map`视图。
*/
implicit def mapAsScalaConcurrentMapConverter[A, B](m: juc.ConcurrentMap[A, B]): AsScala[concurrent.Map[A, B]] =
new AsScala(mapAsScalaConcurrentMap(m))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Dictionary`转换为Scala的可变`Map[String, String]`。
* 返回的Scala `Map[String, String]`由提供的Java `Dictionary`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* @param p 要转换的`Dictionary`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala可变`Map[String, String]`视图。
*/
implicit def dictionaryAsScalaMapConverter[A, B](p: ju.Dictionary[A, B]): AsScala[mutable.Map[A, B]] =
new AsScala(dictionaryAsScalaMap(p))
/**
* 添加一个`asScala`方法,它隐式地将Java的`Properties`转换为Scala的可变`Map[String, String]`。
* 返回的Scala `Map[String, String]`由提供的Java `Properties`支持,通过Scala接口使用它的任何副作用都会通过Java接口可见,反之亦然。
*
* @param p 要转换的`Properties`。
* @return 具有`asScala`方法的对象,该方法返回参数的Scala可变`Map[String, String]`视图。
*/
implicit def propertiesAsScalaMapConverter(p: ju.Properties): AsScala[mutable.Map[String, String]] =
new AsScala(propertiesAsScalaMap(p))
}
这段代码是Scala标准库中的一个trait,提供了一些装饰器方法,用于在Java集合和Scala集合之间进行转换。
这个trait定义了一系列隐式转换方法,例如asScalaIteratorConverter
、enumerationAsScalaIteratorConverter
、iterableAsScalaIterableConverter
等等。这些方法允许在Java集合和对应的Scala集合之间相互转换,以便在使用时能够无缝切换。
该trait还提供了一些单向转换方法,例如asScalaBufferConverter
、asScalaSetConverter
、mapAsScalaMapConverter
等等,用于将特定类型的Java集合转换为对应的Scala集合。
请注意,这段代码只是给出了一个示例,具体应用时可能需要根据实际需求进行适当修改和扩展。
Decorators
import java.{ util => ju }
private[collection] trait Decorators {
/** 包含 `asJava` 转换方法的通用类 */
class AsJava[A](op: => A) {
/** 将 Scala 集合转换为对应的 Java 集合 */
def asJava: A = op
}
/** 包含 `asScala` 转换方法的通用类 */
class AsScala[A](op: => A) {
/** 将 Java 集合转换为对应的 Scala 集合 */
def asScala: A = op
}
/** 包含 `asJavaCollection` 转换方法的通用类 */
class AsJavaCollection[A](i: Iterable[A]) {
/** 将 Scala 的 `Iterable` 转换为 Java 的 `Collection` */
def asJavaCollection: ju.Collection[A] = JavaConversions.asJavaCollection(i)
}
/** 包含 `asJavaEnumeration` 转换方法的通用类 */
class AsJavaEnumeration[A](i: Iterator[A]) {
/** 将 Scala 的 `Iterator` 转换为 Java 的 `Enumeration` */
def asJavaEnumeration: ju.Enumeration[A] = JavaConversions.asJavaEnumeration(i)
}
/** 包含 `asJavaDictionary` 转换方法的通用类 */
class AsJavaDictionary[A, B](m : mutable.Map[A, B]) {
/** 将 Scala 的 `Map` 转换为 Java 的 `Dictionary` */
def asJavaDictionary: ju.Dictionary[A, B] = JavaConversions.asJavaDictionary(m)
}
}
private[collection] object Decorators extends Decorators
以上代码定义了一个名为 Decorators
的特质,其中包含多个类和方法,用于进行Scala集合与Java集合之间的相互转换。
AsJava
类:包含asJava
转换方法,用于将 Scala 集合转换为对应的 Java 集合。AsScala
类:包含asScala
转换方法,用于将 Java 集合转换为对应的 Scala 集合。AsJavaCollection
类:包含asJavaCollection
转换方法,用于将 Scala 的Iterable
转换为 Java 的Collection
。AsJavaEnumeration
类:包含asJavaEnumeration
转换方法,用于将 Scala 的Iterator
转换为 Java 的Enumeration
。AsJavaDictionary
类:包含asJavaDictionary
转换方法,用于将 Scala 的Map
转换为 Java 的Dictionary
。
最后,通过 Decorators
对象来使用这些转换方法。该对象是 Decorators
特质的实例化对象,提供了对外公开的接口以进行集合转换操作。
语法分析
以上源码使用了以下Scala特性:
-
隐式转换(Implicit Conversion):通过定义隐式转换方法,实现了从Java集合到Scala集合的自动转换。例如,
asScalaIteratorConverter
、enumerationAsScalaIteratorConverter
等方法都是通过隐式转换实现的。 -
类型参数化(Type Parameterization):在定义装饰器类时,使用了类型参数来泛化方法的返回类型。例如,
AsJava
和AsScala
类都使用了类型参数A
,使得这些类可以适用于不同类型的集合。 -
特质(Trait):
Decorators
trait 是一个特质,用于定义一组相关的功能。它可以被其他类或对象混入(mixin),以扩展它们的功能。 -
对象(Object):
Decorators
对象是一个单例对象,用于提供对Decorators
trait 中定义的装饰器类和方法的访问。 -
高阶函数(Higher-Order Functions):装饰器类中的方法接受一个传名参数,允许在需要时延迟求值。例如,
AsJava
和AsScala
类的构造函数中的op: => A
参数就是一个传名参数。 -
泛型集合(Generic Collection):装饰器类中的方法接受和返回泛型的集合类型,例如
Iterable[A]
、Collection[A]
、Enumeration[A]
、Dictionary[A, B]
等。 -
包对象(Package Object):在代码中使用了
mutable
包对象,通过导入mutable.Map
,实现对Scala可变Map的引用。
总体而言,以上源码利用了Scala的隐式转换、类型参数化、特质、对象、高阶函数、泛型集合和包对象等多种特性来实现Java集合和Scala集合之间的互相转换。
传名参数
传名参数(Call-by-Name)是一种在函数调用时,实际参数并不立即求值,而是在需要时才进行求值的机制。在Scala中,可以使用=>
符号来定义传名参数。
下面是一个示例代码,展示了如何在Scala中使用传名参数:
def exampleFunc(op: => Int): Unit = {
println("Before calling op")
val result = op
println(s"The result is $result")
}
def expensiveOperation(): Int = {
println("Expensive operation...")
42
}
// 调用exampleFunc,并传递expensiveOperation作为op参数
exampleFunc(expensiveOperation())
在上述示例中,exampleFunc
函数接受一个传名参数op: => Int
。当调用exampleFunc(expensiveOperation())
时,expensiveOperation
函数并没有立即执行,而是在op
被实际使用时才进行求值。输出结果如下:
Before calling op
Expensive operation...
The result is 42
可以看到,在调用exampleFunc
之前并没有打印"Expensive operation…",说明expensiveOperation
并未立即执行。只有在val result = op
这一行代码中,op
才会被求值,进而执行expensiveOperation
函数。
富接口
Rich Interface为Scala集合添加额外的方法:
import java.util.{ArrayList, List}
// 富接口类,扩展了Java的List接口
implicit class RichList[A](list: List[A]) {
// 添加一个自定义方法,用于打印列表中的元素
def printElements(): Unit = {
for (i <- 0 until list.size()) {
println(list.get(i))
}
}
}
// 创建一个Java的ArrayList
val javaList: ArrayList[String] = new ArrayList[String]()
javaList.add("Apple")
javaList.add("Banana")
javaList.add("Orange")
// 将Java的ArrayList转换为Scala的List,并通过富接口调用自定义方法
val scalaList: List[String] = javaList
scalaList.printElements()
在上述示例中,我们首先定义了一个RichList
类,它扩展了Java的List
接口。该类带有一个自定义方法printElements()
,用于打印列表中的元素。
然后,我们创建了一个Java的ArrayList
并向其中添加一些元素。接下来,我们将Java的ArrayList
转换为Scala的List
,并使用富接口调用自定义的printElements()
方法,打印出列表中的元素。
输出结果如下:
Apple
Banana
Orange
通过使用富接口,我们可以为Scala集合添加自定义的方法,使其更加丰富和方便使用。这样,我们可以根据自己的需求来扩展和定制集合的功能。