Question Comment initialiser les valeurs HashSet par construction?


Je dois créer un Set avec des valeurs initiales.

Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");

Y a-t-il un moyen de le faire dans une ligne de code?


518
2018-01-11 12:31


origine


Réponses:


Il y a un raccourci que j'utilise qui n'est pas très efficace, mais qui ne tient que sur une seule ligne:

Set<String> h = new HashSet<>(Arrays.asList("a", "b"));

Encore une fois, ce n'est pas efficace car vous construisez un tableau, convertissez-le en une liste et utilisez cette liste pour créer un ensemble.

Lors de l'initialisation des ensembles finaux statiques, je l'écris habituellement comme ceci:

public static final String[] SET_VALUES = new String[] { "a", "b" };
public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES));

Un peu moins laid et l'efficacité n'a pas d'importance pour l'initialisation statique.


682
2018-01-11 12:38



Les littéraux de collection ont été programmés pour Java 7, mais ne l'ont pas fait. Donc rien d'automatique pour le moment.

Vous pouvez utiliser des goyaves Sets:

Sets.newHashSet("a", "b", "c")

Ou vous pouvez utiliser la syntaxe suivante, qui va créer une classe anonyme, mais c'est hacky:

Set<String> h = new HashSet<String>() {{
    add("a");
    add("b");
}};

294
2018-01-11 12:34



En Java 8 j'utiliserais:

Set<String> set = Stream.of("a", "b").collect(Collectors.toSet());

Cela vous donne un mutable Set pré-initialisé avec "a" et "b". Notez que bien que dans JDK 8 cela retourne un HashSet, la spécification ne le garantit pas, et cela pourrait changer dans le futur. Si vous voulez spécifiquement un HashSet, faites ceci à la place:

Set<String> set = Stream.of("a", "b")
                        .collect(Collectors.toCollection(HashSet::new));

144
2018-01-11 12:34



Il y a plusieurs façons:

Initialisation double accolade

C'est une technique qui crée une classe interne anonyme qui a un initialiseur d'instance qui ajoute Strings à lui-même lorsqu'une instance est créée:

Set<String> s = new HashSet<String>() {{
    add("a");
    add("b");
}}

Gardez à l'esprit que cela va créer une nouvelle sous-classe de HashSet chaque fois qu'il est utilisé, même s'il n'est pas nécessaire d'écrire explicitement une nouvelle sous-classe.

Une méthode d'utilité

Ecrire une méthode qui renvoie un Set ce qui est initialisé avec les éléments souhaités n'est pas trop difficile à écrire:

public static Set<String> newHashSet(String... strings) {
    HashSet<String> set = new HashSet<String>();

    for (String s : strings) {
        set.add(s);
    }
    return set;
}

Le code ci-dessus ne permet que l'utilisation d'un String, mais il ne devrait pas être trop difficile de permettre l'utilisation de n'importe quel type en utilisant des génériques.

Utiliser une bibliothèque

De nombreuses bibliothèques ont une méthode pratique pour initialiser les objets de collections.

Par exemple, Google Collections a un Sets.newHashSet(T...) méthode qui peuplera un HashSet avec des éléments d'un type spécifique.


78
2018-05-24 06:36



Utilisation de Java 10 (ensembles non modifiables)

Set<String> strSet1 = Stream.of("A", "B", "C", "D")
         .collect(Collectors.toUnmodifiableSet());

Utilisation de Java 9 (ensembles non modifiables)

Set<String> strSet6 = Set.of("Apple", "Ball", "Cat", "Dog");

Utilisation de Java 8 (ensembles modifiables)

En utilisant Courant en Java 8.

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

// stream from an array (String[] stringArray)
Set<String> strSet2 = Arrays.stream(stringArray)
         .collect(Collectors.toCollection(HashSet::new));

// stream from a list (List<String> stringList)
Set<String> strSet3 = stringList.stream()
         .collect(Collectors.toCollection(HashSet::new));

Utilisation de Java 8 (ensembles non modifiables)

Utilisation de Collections.unmodifiableSet - On peut utiliser Collections.unmodifiableSet comme:

Set<String> strSet4 = Collections.unmodifiableSet(strSet1);

Mais il semble un peu gênant et nous pouvons écrire notre propre collectionneur comme ceci:

class ImmutableCollector {
    public static <T> Collector<T, Set<T>, Set<T>> toImmutableSet() {
        return Collector.of(HashSet::new, Set::add, (l, r) -> {
            l.addAll(r);
            return l;
        }, Collections::unmodifiablSet);
    }
}

Et puis utilisez-le comme:

Set<String> strSet4 = Stream.of("A", "B", "C", "D")
             .collect(ImmutableCollector.toImmutableSet());

Utiliser Collectors.collectingAndThen - Une autre approche consiste à utiliser la méthode Collectors.collectingAndThen ce qui nous permet d'effectuer des transformations de finition supplémentaires:

import static java.util.stream.Collectors.*;
Set<String> strSet5 = Stream.of("A", "B", "C", "D").collect(collectingAndThen(
   toCollection(HashSet::new),Collections::unmodifiableSet));

Si nous nous soucions seulement de Set alors nous pouvons aussi utiliser Collectors.toSet() au lieu de Collectors.toCollection(HashSet::new).


60
2018-01-11 12:36



Vous pouvez le faire en Java 6:

Set<String> h = new HashSet<String>(Arrays.asList("a", "b", "c"));

Mais pourquoi? Je ne trouve pas cela plus lisible que d'ajouter des éléments explicitement.


26
2017-10-05 07:51



Si vous n'avez qu'une seule valeur initiale dans l'ensemble, cela suffirait:

Set<String> h = Collections.singleton("a");

23
2017-10-29 18:05



Je pense que le plus lisible est d'utiliser simplement Google Guava:

Set<String> StringSet = Sets.newSet("a", "b", "c");

22
2017-07-05 09:30