Scala与Java集合类型转换性能分析与源码解读
时间:2026-08-21 | 作者:风起客 | 阅读:0Ja vaConverters
如何使用
先引入依赖。
import collection.Ja vaConverters._
集合可以显式调用 asJa va、asScala 进行转化。
在代码中,经常会涉及scala和ja va集合的相互转换。很多人会担心这里是否会产生性能问题。下面结合源码,分析一下转换过程带来的代价。
先给出结论:通过适配器模式(Adapter Pattern)实现,时间复杂度为O(1),仅会产生极小的性能开销。
而且,将Ja va集合转换为Scala后再转换回Ja va,得到的是原始对象,并非是Wrapper套Wrapper的形式。
如何实现(源码分析)
以List转换为例
scala => ja va
测试代码:
object Ja vaConverterTest {
def main(args: Array[String]): Unit = {
import collection.Ja vaConverters._
val list = List[String]("A", "B", "C")
val jListWrapper = list.asJa va
println(jListWrapper)
}
}
借助CFR反编译得到:在线反编译工具网址
/*
* Decompiled with CFR 0.150.
*
* Could not load the following classes:
* scala.Predef$
* scala.collection.Ja vaConverters$
* scala.collection.Seq
* scala.collection.immutable.List
* scala.collection.immutable.List$
*/
import scala.Predef$;
import scala.collection.Ja vaConverters$;
import scala.collection.Seq;
import scala.collection.immutable.List;
import scala.collection.immutable.List$;
public final class Ja vaConverterTest$ {
public static final Ja vaConverterTest$ MODULE$;
public static {
new Ja vaConverterTest$();
}
public void main(String[] args) {
List list = List$.MODULE$.apply((Seq)Predef$.MODULE$.wrapRefArray((Object[])new String[]{"A", "B", "C"}));
Predef$.MODULE$.println(Ja vaConverters$.MODULE$.seqAsJa vaListConverter((Seq)list).asJa va());
}
private Ja vaConverterTest$() {
MODULE$ = this;
}
}
根据反编译结果可以发现,调用了Ja vaConverters的方法seqAsJa vaListConverter。
Ja vaConverters
object Ja vaConverters extends DecorateAsJa va with DecorateAsScala
Ja vaConverters的方法全部继承于DecorateAsJa va以及DecorateAsScala。
DecorateAsJa va
DecorateAsJa va定义了一系列隐式转换方法。
关于隐式转换方法,个人的理解就是:提供了一系列类型间的转换供编译器选择。当编译不成功时,编译器会去找合适的隐式方法,将类型进行适当转换,从而使得编译通过。
DecorateAsJa va的方法seqAsJa vaListConverter:
implicit def seqAsJa vaListConverter[A](b : Seq[A]): AsJa va[ju.List[A]] =
new AsJa va(seqAsJa vaList(b))
这便是提供了从:Seq[A] => AsJa va[ju.List[A]] 的隐式类型转换。
因此,集合就获得了asJa va的方法,用于显示的转换。
Decorators
AsJa va对象是Decorators的内部类。
private[collection] object Decorators {
class AsJa va[A](op: => A) {
/** Converts a Scala collection to the corresponding Ja va collection */
def asJa va: A = op
}
//其他内部类
}
op: => A:此处并非传递一个方法,而是名调用(call-by-name)。
这个参数op实际上代表一个代码块。该代码块的返回值为A,在这里也就是AsJa va的泛型ju.List[A]。
这里可以看出,具体将scala集合List转化为util.List的逻辑,在seqAsJa vaList方法里。
AsJa vaConverters
def seqAsJa vaList[A](s: Seq[A]): ju.List[A] = s match {
case null => null
case JListWrapper(wrapped) => wrapped.asInstanceOf[ju.List[A]]
case _ => new SeqWrapper(s)
}
这里按Seq类型进行了分类:
JListWrapper(wrapped):本身就是Ja va List包装成的Scala List,直接去掉包装即可。- 其他非
null情况:new SeqWrapper(s),即将scala List包装为Ja va List。
Wrapper
点进SeqWrapper,看看具体怎么包装的。
private[collection] trait Wrappers {
trait IterableWrapperTrait[A] extends ju.AbstractCollection[A] {
val underlying: Iterable[A]
def size = underlying.size
override def iterator = IteratorWrapper(underlying.iterator)
override def isEmpty = underlying.isEmpty
}
case class IteratorWrapper[A](underlying: Iterator[A]) extends ju.Iterator[A] with ju.Enumeration[A] {
def hasNext = underlying.hasNext
def next() = underlying.next()
def hasMoreElements = underlying.hasNext
def nextElement() = underlying.next()
override def remove() = throw new UnsupportedOperationException
}
case class SeqWrapper[A](underlying: Seq[A]) extends ju.AbstractList[A] with IterableWrapperTrait[A] {
def get(i: Int) = underlying(i)
}
}
SeqWrapper是Wrapper下的一个内部样例类。
它继承了AbstractList,实现了其抽象方法get,以及Iterable接口的迭代器相关方法。
迭代器相关包装实现包括:
IterableWrapperTraitIteratorWrapper
注:ja va集合继承关系:
graph BT
A(AbstractList 抽象类) ---> B(List 接口) ---> D(Collection 接口) ---> E(Iterater 接口)
A ---> C(AbstractCollection 抽象类) ---> D
ja va => scala
详情见JListWrapper,略。
结论
由源码可以看出:对于列表类型的集合类型转换,时间复杂度为O(1)。
并不会对性能产生什么影响,只是做了个适配/包装(实现ja va接口的方法),并不存在集合数据的拷贝。
Map转换的一些点
self 是this的引用。
当MapWrapper为Wrapper内部类的时候,定义的self引用可以将内部类的this和外部类的this进行区分。
class MapWrapper[A, B](underlying: Map[A, B]) extends ju.AbstractMap[A, B] with Serializable { self =>
//一些方法的实现
}
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- Chrome开发者工具高级调试:断点、性能分析与网络监控实战
- 时间:2026-08-31
-
- Safari浏览器控制台查看网页性能与加载时间方法
- 时间:2026-06-09
-
- AMD中国特供RX 9070 GRE突袭上架!4199元起、5月8日开售
- 时间:2025-04-28
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
![Scala与Java集合类型转换性能分析与源码解读_wishdown.com [Scala源码] Scala与Ja va间集合类型转换的性能分析](https://img.wishdown.com/upload/news/20260821cae8c66392dc5f056dece04de4f7054f.webp)