【Java原理系列】 scala JavaConverters原理用法示例源码详解

54 篇文章 1 订阅

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对象中,通过定义隐式类RichIterableRichIteratorRichBufferRichSetRichMap等,为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集合之间进行转换。

这些转换通过asJavaasScala方法实现:

  • 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的方向是通过更具体名称的方法实现的:asJavaCollectionasJavaEnumerationasJavaDictionary

  • 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

该对象继承了DecorateAsJavaDecorateAsScala 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定义了一系列隐式转换方法,例如asJavaIteratorConverterasJavaEnumerationConverterasJavaIterableConverter等等。这些方法允许在Scala集合和对应的Java集合之间相互转换,以便在使用时能够无缝切换。

该trait还提供了一些单向转换方法,例如mutableSeqAsJavaListConverterseqAsJavaListConvertermutableSetAsJavaSetConverter等等,用于将特定类型的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定义了一系列隐式转换方法,例如asScalaIteratorConverterenumerationAsScalaIteratorConverteriterableAsScalaIterableConverter等等。这些方法允许在Java集合和对应的Scala集合之间相互转换,以便在使用时能够无缝切换。

该trait还提供了一些单向转换方法,例如asScalaBufferConverterasScalaSetConvertermapAsScalaMapConverter等等,用于将特定类型的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特性:

  1. 隐式转换(Implicit Conversion):通过定义隐式转换方法,实现了从Java集合到Scala集合的自动转换。例如,asScalaIteratorConverterenumerationAsScalaIteratorConverter等方法都是通过隐式转换实现的。

  2. 类型参数化(Type Parameterization):在定义装饰器类时,使用了类型参数来泛化方法的返回类型。例如,AsJavaAsScala类都使用了类型参数A,使得这些类可以适用于不同类型的集合。

  3. 特质(Trait):Decorators trait 是一个特质,用于定义一组相关的功能。它可以被其他类或对象混入(mixin),以扩展它们的功能。

  4. 对象(Object):Decorators对象是一个单例对象,用于提供对Decorators trait 中定义的装饰器类和方法的访问。

  5. 高阶函数(Higher-Order Functions):装饰器类中的方法接受一个传名参数,允许在需要时延迟求值。例如,AsJavaAsScala类的构造函数中的op: => A参数就是一个传名参数。

  6. 泛型集合(Generic Collection):装饰器类中的方法接受和返回泛型的集合类型,例如Iterable[A]Collection[A]Enumeration[A]Dictionary[A, B]等。

  7. 包对象(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集合添加自定义的方法,使其更加丰富和方便使用。这样,我们可以根据自己的需求来扩展和定制集合的功能。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值