Conversion d'une collection Java en collection Scala

87

Lié à la question Stack Overflow, équivalent Scala du nouveau HashSet (Collection) , comment convertir une collection Java (par java.util.Listexemple) en une collection Scala List?

J'essaie en fait de convertir un appel d'API Java en Spring SimpleJdbcTemplate , qui renvoie a java.util.List<T>, en un Scala immuable HashSet. Donc par exemple:

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

Cela semble fonctionner. La critique est la bienvenue!

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

Réponses:

17

Votre dernière suggestion fonctionne, mais vous pouvez également éviter d'utiliser jcl.Buffer:

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

Notez qu'il scala.collection.immutable.Setest rendu disponible par défaut grâce à Predef.scala.

Jorge Ortiz
la source
9
Cette suggestion ne fonctionne pas là où je veux conserver les informations de type
oxbow_lakes
126

Pour référence future: Avec Scala 2.8, cela pourrait être fait comme ceci:

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

setest un scala.collection.immutable.Set[String]après ça.

Voir également la réponse de Ben James pour une manière plus explicite (en utilisant JavaConverters), qui semble être recommandée maintenant.

robinst
la source
On dirait que maintenant JavaConversionsa des implicites rendant l' toSetappel non nécessaire.
Rajish
@Rajish Je pense que c'est mieux si la conversion est explicite (voir stackoverflow.com/questions/8301947/… )
krookedking
vous avez raison, il vaut mieux utiliser import scala.collection.JavaConverters._
Abhishek Sengupta
62

Si vous voulez être plus explicite que les JavaConversions démontrées dans la réponse de robinst , vous pouvez utiliser JavaConverters:

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

JavaConversions ( réponse de robinst ) et JavaConverters ( réponse de Ben James ) sont obsolètes avec Scala 2.10 .

Au lieu de JavaConversions, utilisez:

import scala.collection.convert.wrapAll._

comme suggéré par aleksandr_hramcov .

Au lieu de JavaConverters, utilisez:

import scala.collection.convert.decorateAll._

Pour les deux, il est également possible d'importer uniquement les conversions / convertisseurs vers Java ou Scala respectivement, par exemple:

import scala.collection.convert.wrapAsScala._

Mise à jour: La déclaration ci-dessus selon laquelle JavaConversions et JavaConverters étaient obsolètes semble être fausse. Il y avait des propriétés obsolètes dans Scala 2.10, ce qui entraînait des avertissements d'obsolescence lors de leur importation. Les importations alternatives ici semblent donc être uniquement des alias. Bien que je les préfère toujours, comme à mon humble avis, les noms sont plus appropriés.

stempler
la source
Pourquoi dites-vous que les JavaConversions et les JavaConverters sont obsolètes? Dans la documentation actuelle 2.11.8, les deux ne sont pas marqués comme étant obsolètes et ils n'ont pas non plus de référence à 'decorateAll' ou 'wrapAll' indiquant que c'est l'usage nouveau et préféré.
Joost den Boer
@JoostdenBoer Semble il y avait quelques décorateurs dépréciées il à Scala 2.10, mais ils semblent avoir été enlevés à nouveau avec Scala 2,11.
stempler
14

Vous pouvez également explorer cette excellente bibliothèque: scalaj-collection qui a une conversion bidirectionnelle entre les collections Java et Scala. Dans votre cas, pour convertir une java.util.List en liste Scala, vous pouvez le faire:

val list = new java.util.ArrayList[java.lang.String]
list.add("A")
list.add("B")
list.asScala
Surya Suravarapu
la source
1
Cette bibliothèque est la meilleure chose qui soit. Fonctionne vraiment très bien.
Michael Neale
6
Revisitant ceci après quelques années, les JavaConverters de Scala sont la voie à suivre.
Surya Suravarapu
4

À partir de Scala 2.13, le package scala.jdk.CollectionConvertersremplace les packages 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")
Xavier Guihot
la source
3
val array = java.util.Arrays.asList("one","two","three").toArray

val list = array.toList.map(_.asInstanceOf[String])
jamesqiu
la source
c'est une excellente réponse et a résolu mon problème. La plupart des méthodes mentionnées sur Internet convertissent simplement (par exemple) java.util.List [java.lang.Long] en scala.collection.immutable.List [java.lang.Long]. Donc, cette méthode a fonctionné pour moi pour le convertir en scala.collection.immutable.List [scala.Long]
ajkl
2

Vous pouvez ajouter les informations de type dans l'appel toArray pour que l'ensemble soit paramétré:

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

Cela peut être préférable car le package de collections subit une refonte majeure pour Scala 2.8 et le package scala.collection.jcl disparaît

Aaron
la source
1

Vous pouvez convertir la collection Java en un tableau, puis créer une liste Scala à partir de cela:

val array = java.util.Arrays.asList("one","two","three").toArray
val list = List.fromArray(array)
Fabian Steeg
la source
2
Ce n'est pas génial parce que mon java.util.List revient d'une API Java sous forme de liste paramétrée (donc mon appel à l'API donne un java.util.List <String>) - J'essaye de tourner ceci into a scala immutable HashSet
oxbow_lakes
1

Un autre moyen simple de résoudre ce problème:

import collection.convert.wrapAll._
aleksandr_hramcov
la source