如何将java.util.List[java.lang.Double]转换为Scala的List[Double]?

8

我希望以一种高效的方式将Java的Double类型列表(java.util.List[java.lang.Double])转换为Scala的Double类型列表(List[Double])。

目前,我正在对列表进行映射,将每个Double值转换为Scala Double。我不想遍历每个值,正在寻找更有效的方法。

import collection.JavaConversions._
import collection.mutable.Buffer

val j: java.util.List[java.lang.Double] = Buffer(new java.lang.Double(1.0), new java.lang.Double(2.0))
val s: List[Double] = ...

我看到了一些从Scala转向Java的文档,但是很少有相反的情况。


我看过从Scala到Java的文档,但是很少有反向的。你知道吗?愿意分享一下这些信息吗?;-) - Make42
我找到了答案:https://stackoverflow.com/q/46830217/4533188 - Make42
2个回答

20

建议使用JavaConverters而不是JavaConversions

import collection.JavaConverters._
import scala.collection.breakOut
val l: List[Double] = j.asScala.map(_.doubleValue)(breakOut)
doubleValue将把java.lang.Double转换为scala.DoublebreakOut告诉它要将map的结果生成一个List,而不必再遍历一次以转换为List。如果您不介意额外的遍历,也可以只使用toList代替breakOut
Java类与Scala类是完全不同的对象;这不仅仅是名称更改。因此,如果没有遍历,就无法进行转换。您需要创建一个完全新的集合,然后查看每个元素以(转换并)移动它们。
类型不同的原因是java.lang.Double是“包装的基本类型”,而scala.Double等价于Java的double基本类型。此处的转换实质上是“解包装”原语。

有没有一种方法可以在不进行任何遍历的情况下完成它?也许这是不可能的,但我天真地想象转换不会涉及任何遍历。 - Erik Shilts
请注意,如果您愿意接受 Seq 而不是精确的 List,那么您可以通过在调用 map 之前调用 view 方法将 Scala 转换的 Java List 转换为视图来避免遍历。 这将为您提供一个惰性评估的 SeqView,该视图将根据需要对元素应用转换。 - reggert

0
import collection.JavaConverters._

val javaList : java.util.List[Double] = ...
val scalaList : List[Double] = j.asScala.toList

这可以将java.util.list[Double]转换为List[Double],但棘手的部分还包括从java.lang.Double转换为Scala Double。 - Erik Shilts
1
@Erik,这不是强制类型转换:asScala会遍历基于Java的集合并构建一个全新的基于Scala的集合。因为这两个类是完全不同的,所以它必须这样做。 - dhg
@dhg,你实际上是错的。asScala并不遍历集合;asScala创建了一个视图,指向原始集合。它是toList执行实际遍历。请参见scala.collection.convert.Wrappers特质:它包含这些视图的实现,很明显它们只将集合操作转发到原始Java集合。 - Vladimir Matveev
@dhg,你是对的,然而javaList.asScala.map(_.doubleValue).toList会执行两次遍历,第一次在map中进行,第二次在toList中进行。 - Vladimir Matveev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接