从 java 到 scala 集合的隐式转换成本

Cost of implicit conversion from java to scala collections

我想知道从 java 集合到 scala 集合的隐式转换的成本。在 this doc 中有几个隐式双向转换,据说 "converting from a source type to a target type and back again will return the original source object".

我的结论是成本应该很小(包装),但还是多少钱?

我问这个问题是因为我在某些 Scala 代码中使用了 java 集,当我导入 asScalaSet 时它被隐式转换为 Scala 集(我在某些地方确实需要它)。但是,对于 size()

等非常小的访问器来说,这可能是一个随之而来的开销

有人知道吗?

我决定从实际的角度来回答你的问题。我使用以下简单的 JMH 基准来测试原始 scala 集合的每秒操作数并转换一个(使用隐式转换)。

请找到以下基准代码:

import org.openjdk.jmh.annotations._

import scala.collection.JavaConversions._

@State(Scope.Thread)
class WrapperBenchmark {

  val unwrappedCollection = (1 to 100).toSet
  val wrappedCollection: java.util.Set[Int] = (1 to 100).toSet[Int]

  @Benchmark
  def measureUnwrapped: Int = unwrappedCollection.size

  @Benchmark
  def measureWrapped: Int = wrappedCollection.size()
}

我为 运行 使用了 sbt 和 sbt-jmh 插件。请在下面查找结果:

[info] Benchmark                           Mode  Cnt          Score         Error  Units
[info] WrapperBenchmark.measureUnwrapped  thrpt  200  353214968.844 ± 1534779.932  ops/s
[info] WrapperBenchmark.measureWrapped    thrpt  200  284669396.241 ± 4223983.126  ops/s

所以基本上根据结果,确实有开销。我将尝试继续我的研究,在稍后更新此问题时提供原因。

如果你想让我分享完整的 sbt 项目以供你未来研究,请告诉我。

这是使用 Scala 2.13.1 的 jmh 基准测试结果 CollectionConverters

import org.openjdk.jmh.annotations._
import scala.jdk.CollectionConverters._
import java.{util => ju}

@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So31830028 {
  val size = 1000000
  val scalaSet: Set[Int] = (1 to size).toSet
  val javaSet: ju.Set[Int]  = (1 to size).toSet.asJava

  @Benchmark def scala = scalaSet.size
  @Benchmark def scalaAsJava = scalaSet.asJava.size
  @Benchmark def java = javaSet.size
  @Benchmark def javaAsScala = javaSet.asScala.size
}

其中 sbt "jmh:run -i 10 -wi 5 -f 2 -t 1 bench.So31830028" 给出

[info] Benchmark                     Mode  Cnt          Score          Error   Units
[info] So31830028.java              thrpt   20  356515729.840 ± 64691657.672   ops/s
[info] So31830028.javaAsScala       thrpt   20  270053471.338 ± 36854051.611   ops/s
[info] So31830028.scala             thrpt   20  448415156.726 ± 53674976.259   ops/s
[info] So31830028.scalaAsJava       thrpt   20  211808793.234 ± 57898858.737   ops/s

确实有一笔相当大的费用。