2014-05-23 6 views
5

Ich möchte eine Java-Liste von Java-Doubles (java.util.List [java.lang.Double]) in eine Scala-Liste von Scala verdoppelt (List [Double]) auf effiziente Weise konvertieren.Wie konvertiert man java.util.List [java.lang.Double] in Scalas Liste [Double]?

Zur Zeit übergebe ich die Liste, indem ich jeden Double-Wert in eine Scala Double umwandle. Ich würde es vorziehen, nicht jeden Wert abzubilden und suche nach einer effizienteren Methode, dies zu tun.

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] = ... 

Ich habe Dokumentation gesehen, von Scala zu gehen -> Java, aber nicht viel in die andere Richtung gehen.

+0

"Ich habe Dokumentationen von Scala -> Java gesehen, aber nicht viel anders." ... hast du jetzt? Möchten Sie diese Informationen weitergeben? ;-) – Make42

+0

Ich fand die Antwort: https://stackoverflow.com/q/46830217/4533188 – Make42

Antwort

14

Die Empfehlung ist JavaConverters zu verwenden, nicht JavaConversions:

import collection.JavaConverters._ 
import scala.collection.breakOut 
val l: List[Double] = j.asScala.map(_.doubleValue)(breakOut) 

doubleValue es von einem java.lang.Double in eine scala.Double konvertieren. breakOut sagt es, um eine List als Ergebnis der map zu produzieren, ohne es ein anderes Mal durchlaufen zu müssen, um zu einem List zu konvertieren. Sie könnten auch einfach toList anstelle von breakOut tun, wenn Sie nicht auf die zusätzliche Traversal kümmern.

Die Java-Klassen sind völlig verschiedene Objekte von den Scala-Einsen; es ist nicht nur eine Namensänderung. Somit wäre es unmöglich, ohne zu verfahren, umzuwandeln. Sie müssen eine völlig neue Sammlung erstellen und dann jedes Element betrachten, um es umzuwandeln und es zu verschieben.

Der Grund für die unterschiedlichen Typen ist, dass java.lang.Double ein "boxed primitive" ist, wohingegen scala.Double dem doppelten Java-Primitiv entspricht. Die Umwandlung hier ist im Wesentlichen "Unboxing" das Primitive.

+0

Gibt es einen Weg, es ohne irgendwelche Durchquerungen zu tun? Vielleicht ist das nicht möglich, aber ich stelle mir naiv vor, dass Casting keine Traversierungen beinhaltet. –

+0

Beachten Sie, dass Sie das Traversieren vermeiden können, indem Sie die Scala-konvertierte Java-Liste in eine Ansicht konvertieren, indem Sie die 'view'-Methode aufrufen, bevor Sie' map' aufrufen, wenn Sie bereit sind, eine 'Seq' statt einer' List' zu akzeptieren '. Das wird Ihnen eine faul ausgewertete "SeqView" geben, die die Konvertierungen auf die Elemente bei Bedarf anwenden wird. – reggert

0
import collection.JavaConverters._ 

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

Dies ist in der Lage, eine java.util.list [Double] in eine Liste [Double] zu werfen, aber der knifflige Teil ist Konvertierung von java.lang.Double zu Scala Double. –

+1

@Erik, Es ist keine Besetzung: 'asScala' durchquert die Java-basierte Sammlung und erstellt eine brandneue scala-basierte Sammlung. Es muss, da die Klassen komplett verschieden sind. – dhg

+0

@ dhg, Sie sind tatsächlich falsch. 'asScala' durchläuft keine Sammlung; 'asScala' erstellt eine * Ansicht * in der ursprünglichen Sammlung. Es ist "toList", die tatsächliche Traversierung durchführt. Siehe Eigenschaft "scala.collection.convert.Wrappers": Sie enthält Implementierungen dieser Ansichten, und es ist offensichtlich, dass sie nur Sammelvorgänge an die ursprünglichen Java-Sammlungen weiterleiten. –