Conversione di una raccolta Java in una raccolta Scala


88

In relazione alla domanda Stack Overflow Equivalente in Scala del nuovo HashSet (Collection) , come posso convertire una raccolta Java ( java.util.Listdiciamo) in una raccolta Scala List?

In realtà sto cercando di convertire una chiamata API Java in Spring SimpleJdbcTemplate , che restituisce a java.util.List<T>, in una scala immutabile HashSet. Quindi per esempio:

val l: java.util.List[String] = javaApi.query( ... )
val s: HashSet[String] = //make a set from l

Sembra funzionare. Le critiche sono benvenute!

import scala.collection.immutable.Set
import scala.collection.jcl.Buffer 
val s: scala.collection.Set[String] =
                      Set(Buffer(javaApi.query( ... ) ) : _ *)

Risposte:


17

Il tuo ultimo suggerimento funziona, ma puoi anche evitare di usare jcl.Buffer:

Set(javaApi.query(...).toArray: _*)

Nota che scala.collection.immutable.Setè reso disponibile di default grazie a Predef.scala.


9
Questo suggerimento non funziona dove voglio mantenere le informazioni sul tipo
oxbow_lakes

127

Per riferimento futuro: con Scala 2.8, potrebbe essere fatto in questo modo:

import scala.collection.JavaConversions._
val list = new java.util.ArrayList[String]()
list.add("test")
val set = list.toSet

setè un scala.collection.immutable.Set[String]dopo questo.

Vedi anche la risposta di Ben James per un modo più esplicito (usando JavaConverters), che sembra essere consigliato ora.


Sembra che ora JavaConversionsabbia alcune implicazioni che rendono la toSetchiamata non necessaria.
Rajish

@Rajish Penso che sia meglio se la conversione è esplicito (vedi stackoverflow.com/questions/8301947/... )
krookedking

hai ragione, è meglio usare import scala.collection.JavaConverters._
Abhishek Sengupta

62

Se vuoi essere più esplicito rispetto alle JavaConversions dimostrate nella risposta di robinst , puoi usare JavaConverters:

import scala.collection.JavaConverters._
val l = new java.util.ArrayList[java.lang.String]
val s = l.asScala.toSet

25

JavaConversions ( risposta di robinst ) e JavaConverters ( risposta di Ben James ) sono stati deprecati con Scala 2.10 .

Invece di JavaConversions usa:

import scala.collection.convert.wrapAll._

come suggerito da aleksandr_hramcov .

Invece di JavaConverters usa:

import scala.collection.convert.decorateAll._

Per entrambi c'è anche la possibilità di importare solo le conversioni / convertitori rispettivamente in Java o in Scala, es:

import scala.collection.convert.wrapAsScala._

Aggiornamento: l'affermazione sopra che JavaConversions e JavaConverters erano deprecati sembra essere sbagliata. C'erano alcune proprietà deprecate in Scala 2.10, che generavano avvisi di deprecazione durante l'importazione. Quindi le importazioni alternative qui sembrano essere solo alias. Anche se li preferisco ancora, come IMHO i nomi sono più appropriati.


Perché dici che JavaConversions e JavaConverters sono deprecati? Nella documentazione corrente 2.11.8 entrambi non sono contrassegnati come deprecati e inoltre non hanno un riferimento a 'decorateAll' o 'wrapAll' affermando che è l'uso nuovo e preferito.
Joost den Boer

@JoostdenBoer sembra che ci sono stati alcuni decoratori obsolete a Scala 2.10, anche se sembrano essere stati rimossi di nuovo con Scala 2.11.
Stempler

14

Potresti anche voler esplorare questa eccellente libreria: scalaj-collection che ha una conversione a due vie tra le collezioni Java e Scala. Nel tuo caso, per convertire un java.util.List in Scala List puoi farlo:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala

1
Quella biblioteca è la cosa più bella di sempre. Funziona davvero bene.
Michael Neale

7
Rivisitando questo aspetto dopo un paio d'anni, i JavaConverters di Scala sono la strada da percorrere.
Surya Suravarapu

5

Iniziando Scala 2.13, il pacchetto scala.jdk.CollectionConverterssostituisce i pacchetti scala.collection.JavaConverters/JavaConversions._:

import scala.jdk.CollectionConverters._

// val javaList: java.util.List[String] = java.util.Arrays.asList("one","two","three")
javaList.asScala
// collection.mutable.Buffer[String] = Buffer("one", "two", "three")
javaList.asScala.toSet
// collection.immutable.Set[String] = Set("one", "two", "three")

3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])

questa è un'ottima risposta e ha risolto il mio problema. La maggior parte dei metodi menzionati su Internet converte semplicemente (es.) Java.util.List [java.lang.Long] in scala.collection.immutable.List [java.lang.Long]. Quindi questo metodo ha funzionato per me per convertirlo in scala.collection.immutable.List [scala.Long]
ajkl

2

È possibile aggiungere le informazioni sul tipo nella chiamata toArray per rendere il Set parametrizzato:

 val s = Set(javaApi.query(....).toArray(new Array[String](0)) : _*)

Questo potrebbe essere preferibile in quanto il pacchetto collections sta subendo un'importante rielaborazione per Scala 2.8 e il pacchetto scala.collection.jcl non sarà più disponibile


1

Puoi convertire la raccolta Java in un array e quindi creare un elenco Scala da quello:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)

2
Questo non è eccezionale perché il mio java.util.List sta tornando da un'API Java come un elenco parametrizzato (quindi la mia chiamata all'API produce un java.util.List <String>) - Sto cercando di trasformarlo in una scala immutabile HashSet
oxbow_lakes

1

Un altro modo semplice per risolvere questo problema:

import collection.convert.wrapAll._
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.