2014-05-23 41 views
5

vorrei convertire un elenco Java di Java raddoppia (java.util.List [java.lang.Double]) per una lista Scala di Scala raddoppia (Lista [Doppia]) in modo efficiente.Come convertire java.util.List [java.lang.Double] nella lista di Scala [Double]?

Attualmente sto mappatura oltre l'elenco convertendo ogni valore Double a un doppio Scala. Preferirei non mappare su ogni valore e sto cercando un modo più efficiente per farlo.

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

Ho visto la documentazione passare da Scala -> Java, ma non molto sta andando nella direzione opposta.

+0

"Ho visto la documentazione per andare da Scala -> Java, ma non molto sta andando dall'altra parte." ... hai fatto ora? Cura di condividere queste informazioni? ;-) – Make42

+0

Ho trovato la risposta: https://stackoverflow.com/q/46830217/4533188 – Make42

risposta

14

La raccomandazione è di usare JavaConverters, non JavaConversions:

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

doubleValue convertirà da un java.lang.Double in un scala.Double. breakOut dice di produrre un List come il risultato della map, senza dover attraversare un'altra volta convertire in List. Potresti anche solo fare toList invece di breakOut se non ti interessa l'attraversamento extra.

Le classi Java sono oggetti completamente diversi da quelli di Scala; non è solo un cambio di nome. Quindi, sarebbe impossibile convertire senza attraversare. Devi creare una collezione completamente nuova e poi guardare ogni elemento per convertirlo e spostarlo.

La ragione per cui i tipi sono diverso è che java.lang.Double è un "boxed primitivo", mentre scala.Double è equivalente al doppio primitivo di Java. La conversione qui è essenzialmente "unboxing" il primitivo.

+0

C'è un modo per farlo senza attraversamenti? Forse non è possibile, ma immagino ingenuamente che il casting non comporterà alcuna traversata. –

+0

Nota che se sei disposto ad accettare un 'Seq' piuttosto che un' List' con precisione, puoi evitare l'attraversamento convertendo l''Elenco' Java convertito in Scala in una vista chiamando il metodo 'view' prima di chiamare' map '. Questo ti darà un 'SeqView' ponderato che applicherà le conversioni agli elementi in base alle necessità. – reggert

0
import collection.JavaConverters._ 

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

Questo è in grado di lanciare un java.util.List [Doppia] a una lista di [Doppia], ma la parte difficile è anche convertendo da java.lang.Double a Scala Double. –

+1

@Erik, Non è un cast: 'asScala' attraversa la raccolta basata su Java e crea una nuova collezione scala-based. Deve perché le classi sono completamente diverse. – dhg

+0

@ dhg, in realtà sei sbagliato. 'asScala' non attraversa una collezione; 'asScala' crea una * vista * nella collezione originale. È 'tolist' che esegue l'attraversamento effettivo. Vedere la caratteristica 'scala.collection.convert.Wrappers': contiene le implementazioni di queste viste ed è ovvio che inoltrano solo le operazioni di raccolta alle raccolte Java originali. –