Comment convertir un tableau en un ensemble en Java


718

Je voudrais convertir un tableau en un ensemble en Java. Il existe des façons évidentes de le faire (c'est-à-dire avec une boucle) mais je voudrais quelque chose d'un peu plus net, quelque chose comme:

java.util.Arrays.asList(Object[] a);

Des idées?

Réponses:


1228

Comme ça:

Set<T> mySet = new HashSet<>(Arrays.asList(someArray));

En Java 9+, si l'ensemble non modifiable est correct:

Set<T> mySet = Set.of(someArray);

Dans Java 10+, le paramètre de type générique peut être déduit du type de composant de tableaux:

var mySet = Set.of(someArray);

10
Je laisserais de côté le dernier <T>, sinon joli oneliner!
despote

165
@dataoz: faux; Arrays.asListest O (1).
SLaks

67
Notez que si vous utilisez cette méthode sur un tableau de primitives telles que int [], elle renverra un List <int []>, vous devez donc utiliser des classes wrapper pour obtenir le comportement souhaité.
T. Markle

6
@AjayGautam: Ce n'est qu'à Guava.
SLaks

10
Je prends la lisibilité sur l'efficacité (presque) à chaque fois: blog.codinghorror.com/…
David Carboni

222
Set<T> mySet = new HashSet<T>();
Collections.addAll(mySet, myArray);

C'est Collections.addAll (java.util.Collection, T ...) de JDK 6.

De plus: que faire si notre tableau est plein de primitives?

Pour JDK <8, j'écrirais simplement la forboucle évidente pour effectuer le bouclage et l'ajout à l'ensemble en une seule passe.

Pour JDK> = 8, une option intéressante est quelque chose comme:

Arrays.stream(intArray).boxed().collect(Collectors.toSet());

5
Vous pouvez le faire avec java.util.Collections.addAll. De plus, je ne recommanderais plus les collections Commons, sans qu'il soit généré et que la goyave existe.
ColinD

14
+1 pour être plus efficace que la réponse de SLaks, même s'il ne s'agit pas d'une ligne unique.
Adrian

1
@Adrian, je remets cela en question. Je pense que ce addAllsera O ( n ).
Steve Powell

1
Je crois que le point d'Adrian était sur la façon dont la solution de SLaks crée une instance de List qui est finalement rejetée. L'impact réel de cette différence est probablement extrêmement minime, mais pourrait dépendre du contexte dans lequel vous faites cela - des boucles serrées ou des ensembles très grands peuvent se comporter très différemment entre ces deux options.
JavadocMD du

13
Selon le javadoc Collections.addAll () (Java 6): "Le comportement de cette méthode pratique est identique à celui de c.addAll (Arrays.asList (elements)), mais cette méthode est susceptible de s'exécuter beaucoup plus rapidement sous la plupart des implémentations. "
Bert F

124

Avec la goyave, vous pouvez faire:

T[] array = ...
Set<T> set = Sets.newHashSet(array);

27
également ImmutableSet.copyOf (tableau). (J'aime souligner aussi, je suppose.)
Kevin Bourrillion

Pour une liste fixe d'éléments que vous pouvez utiliser: ImmutableSet.of (e1, e2, ..., en). Notez que vous ne pourrez pas modifier cet ensemble après sa création.
pisaruk

1
Soyez averti, le javadoc de la goyave dit: "Cette méthode n'est pas vraiment très utile et sera probablement déconseillée à l'avenir." Ils pointent vers la norme new HashSet<T>(Arrays.asList(someArray)). Voir google.github.io/guava/releases/19.0/api/docs/com/google/common/…
Alexander Klimetschek

68

Java 8:

String[] strArray = {"eins", "zwei", "drei", "vier"};

Set<String> strSet = Arrays.stream(strArray).collect(Collectors.toSet());
System.out.println(strSet);
// [eins, vier, zwei, drei]

2
Vaut-il la peine de faire cela en parallèle?
Raffi Khatchadourian

@RaffiKhatchadourian Cela ne se fait pas nécessairement en parallèle. Arrays.stream ne fait aucune promesse sur le flux. Pour cela, vous devrez appeler parallel () sur le flux résultant.
Felix S

Vous pouvez également appeler parallelStream (). Pour répondre à la question de @ RaffiKhatchadourian, probablement pas. Essayez de mesurer si vous remarquez des problèmes de performances.
Randy the Dev

6
Évitez généralement les parallèles. Par défaut, il utilise un seul pool de threads à travers votre application, et la surcharge pour démarrer les threads et rejoindre est pire que le streaming séquentiel à travers des centaines d'éléments. Ce n'est que dans très peu de situations que le parallèle apporte réellement des avantages.
tkruse

45

Varargs fonctionnera aussi!

Stream.of(T... values).collect(Collectors.toSet());

2
bien mieux que 2-3 doublures.
senseiwu

30

Java 8

Nous avons également la possibilité d'utiliser Stream. Nous pouvons obtenir un flux de différentes manières:

Set<String> set = Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new));
System.out.println(set);

String[] stringArray = {"A", "B", "C", "D"};
Set<String> strSet1 = Arrays.stream(stringArray).collect(Collectors.toSet());
System.out.println(strSet1);

// if you need HashSet then use below option.
Set<String> strSet2 = Arrays.stream(stringArray).collect(Collectors.toCollection(HashSet::new));
System.out.println(strSet2);

Le code source de Collectors.toSet()montre que les éléments sont ajoutés un par un à a HashSetmais la spécification ne garantit pas que ce sera un HashSet.

"Il n'y a aucune garantie sur le type, la mutabilité, la sérialisation ou la sécurité des threads de l'ensemble renvoyé."

Il est donc préférable d'utiliser la dernière option. La sortie est: [A, B, C, D] [A, B, C, D] [A, B, C, D]

Ensemble immuable (Java 9)

Java 9 a introduit Set.ofune méthode d'usine statique qui renvoie un ensemble immuable pour les éléments fournis ou le tableau.

@SafeVarargs
static <E> Set<E> of​(E... elements)

Consultez les Méthodes d'usine statiques définies immuables pour plus de détails.

Ensemble immuable (Java 10)

Nous pouvons également obtenir un ensemble immuable de deux manières:

  1. Set.copyOf(Arrays.asList(array))
  2. Arrays.stream(array).collect(Collectors.toUnmodifiableList());

La méthode Collectors.toUnmodifiableList()utilise en interne l' Set.ofintroduction de Java 9. Consultez également ma réponse pour en savoir plus.


1
+1 pour Stream.of()- je ne le connaissais pas. Un petit problème Collectors.toSet(): vous dites que la spécification ne garantit pas l'ajout d'éléments un par un, mais c'est ce que cela signifie par: "s'accumule ... dans un nouveau Set". Et c'est plus lisible - donc préférable à mon avis, si vous n'avez pas besoin des garanties de type concret, de mutabilité, de sérialisation et de sécurité des threads.
Andrew Spencer

@AndrewSpencer Spec ne garantit pas que l'implémentation définie sera HashSet. Cela garantit seulement que ce sera un Setet c'est ce que je veux dire. J'espère que je l'ai clarifié.
akhil_mittal

Désolé, et merci, je l'ai mal interprété comme signifiant «spéc ne garantit pas ajouté un par un» plutôt que «spéc ne garantit pas un HashSet». Proposition d'une modification pour clarifier.
Andrew Spencer

19

Après cela, Arrays.asList(array)vous pouvez exécuterSet set = new HashSet(list);

Voici un exemple de méthode, vous pouvez écrire:

public <T> Set<T> GetSetFromArray(T[] array) {
    return new HashSet<T>(Arrays.asList(array));
}

J'espérais une méthode qui renvoie un ensemble directement à partir d'un tableau, existe-t-il?

1
Vous pouvez écrire le vôtre, si vous êtes si impatient :)
Petar Minchev

12

Dans les collections Eclipse , les éléments suivants fonctionnent:

Set<Integer> set1 = Sets.mutable.of(1, 2, 3, 4, 5);
Set<Integer> set2 = Sets.mutable.of(new Integer[]{1, 2, 3, 4, 5});
MutableSet<Integer> mutableSet = Sets.mutable.of(1, 2, 3, 4, 5);
ImmutableSet<Integer> immutableSet = Sets.immutable.of(1, 2, 3, 4, 5);

Set<Integer> unmodifiableSet = Sets.mutable.of(1, 2, 3, 4, 5).asUnmodifiable();
Set<Integer> synchronizedSet = Sets.mutable.of(1, 2, 3, 4, 5).asSynchronized();
ImmutableSet<Integer> immutableSet = Sets.mutable.of(1, 2, 3, 4, 5).toImmutable();

Remarque: je suis un committer pour les collections Eclipse


7

Rapidement: vous pouvez faire:

// Fixed-size list
List list = Arrays.asList(array);

// Growable list
list = new LinkedList(Arrays.asList(array));

// Duplicate elements are discarded
Set set = new HashSet(Arrays.asList(array));

et inverser

// Create an array containing the elements in a list
Object[] objectArray = list.toArray();
MyClass[] array = (MyClass[])list.toArray(new MyClass[list.size()]);

// Create an array containing the elements in a set
objectArray = set.toArray();
array = (MyClass[])set.toArray(new MyClass[set.size()]);

6

J'ai écrit ci-dessous des conseils ci-dessus - volez-le ... c'est bien!

/**
 * Handy conversion to set
 */
public class SetUtil {
    /**
     * Convert some items to a set
     * @param items items
     * @param <T> works on any type
     * @return a hash set of the input items
     */
    public static <T> Set<T> asSet(T ... items) {
        return Stream.of(items).collect(Collectors.toSet());
    }
}

Arrays.stream peut être meilleur que Stream.of pour ce qui précède.
Ashley Frieze du

5

Il y a eu beaucoup de bonnes réponses déjà, mais la plupart d'entre eux ne fonctionnera pas avec tableau de primitives (comme int[], long[], char[], byte[], etc.)

En Java 8 et supérieur, vous pouvez encadrer le tableau avec:

Integer[] boxedArr = Arrays.stream(arr).boxed().toArray(Integer[]::new);

Convertissez ensuite en ensemble à l'aide de stream:

Stream.of(boxedArr).collect(Collectors.toSet());

0

Parfois, l'utilisation de certaines bibliothèques standard aide beaucoup. Essayez de regarder les collections Apache Commons . Dans ce cas, vos problèmes sont simplement transformés en quelque chose comme ça

String[] keys = {"blah", "blahblah"}
Set<String> myEmptySet = new HashSet<String>();
CollectionUtils.addAll(pythonKeywordSet, keys);

Et voici les CollectionsUtils javadoc


4
l'utilisateur pourrait ne pas utiliser apache commons
Adrian

si l'utilisateur n'utilise pas apache commons, alors c'est sa première erreur.
Jeryl Cook

3
pourquoi voudriez-vous utiliser cela au lieu de java.util.Collections.addAll(myEmptySet, keys);??
djeikyb

0

Utiliser CollectionUtilsou à ArrayUtilspartir destanford-postagger-3.0.jar

import static edu.stanford.nlp.util.ArrayUtils.asSet;
or 
import static edu.stanford.nlp.util.CollectionUtils.asSet;

  ...
String [] array = {"1", "q"};
Set<String> trackIds = asSet(array);

0

En Java 10 :

String[] strs = {"A", "B"};
Set<String> set = Set.copyOf(Arrays.asList(strs));

Set.copyOfrenvoie un Setélément non modifiable contenant les éléments du donné Collection.

 Le donné Collectionne doit pas l'être nullet ne doit contenir aucun nullélément.


0
private Map<Integer, Set<Integer>> nobreaks = new HashMap();
nobreaks.put(1, new HashSet(Arrays.asList(new int[]{2, 4, 5})));
System.out.println("expected size is 3: " +nobreaks.get(1).size());

la sortie est

expected size is 3: 1

le changer en

nobreaks.put(1, new HashSet(Arrays.asList( 2, 4, 5 )));

la sortie est

expected size is 3: 3

-1

Pour tous ceux qui résolvent pour Android:

Kotlin Collections Solution

L'astérisque *est l' spreadopérateur. Il applique tous les éléments d'une collection individuellement, chacun étant passé dans l'ordre à un varargparamètre de méthode. Il équivaut à:

val myArray = arrayOf("data", "foo")
val mySet = setOf(*myArray)

// Equivalent to
val mySet = setOf("data", "foo")

// Multiple spreads ["data", "foo", "bar", "data", "foo"]
val mySet = setOf(*myArray, "bar", *myArray)

La transmission d'aucun paramètre setOf()entraîne un ensemble vide.

De plus setOf, vous pouvez également utiliser n'importe lequel de ces éléments pour un type de hachage spécifique:

hashSetOf()
linkedSetOf()
mutableSetOf()
sortableSetOf()

Voici comment définir explicitement le type d'élément de collection.

setOf<String>()
hashSetOf<MyClass>()

-2

new HashSet<Object>(Arrays.asList(Object[] a));

Mais je pense que ce serait plus efficace:

final Set s = new HashSet<Object>();    
for (Object o : a) { s.add(o); }         

Ce ne serait pas vraiment plus efficace (du moins ne vaut-il pas la peine d'y penser).
ColinD

3
Avec la version constructeur, la capacité initiale du HashSetest définie en fonction de la taille du tableau, par exemple.
ColinD

3
cette réponse n'est pas aussi stupide qu'il n'y paraît: 'Collections.addAll (mySet, myArray);' de java.util.Collections utilise le même itérateur mais plus une opération booléenne. De plus, comme Bert F l'a souligné, Collections.addAll "s'exécutera probablement beaucoup plus rapidement dans la plupart des implémentations" que c.addAll (Arrays.asList (elements))
Zorb

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.