Comment initialiser les valeurs HashSet par construction?

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

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

Est-il possible de le faire en une seule ligne de code?

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

 Set 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 généralement comme ceci:

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

Légèrement moins moche et efficacité ne compte pas pour l’initialisation statique.

Les littéraux de collection étaient programmés pour Java 7, mais ne sont pas entrés. Donc, rien d’automatique encore.

Vous pouvez utiliser les Sets de goyave:

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

Ou vous pouvez utiliser la syntaxe suivante, qui créera une classe anonyme, mais elle est pirate:

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

En Java 8, j’utiliserais:

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

Cela vous donne un Set mutable pré-initialisé avec “a” et “b”. Notez que même si JDK 8 renvoie un HashSet , la spécification ne le garantit pas et cela pourrait changer à l’avenir. Si vous souhaitez spécifiquement un HashSet , procédez comme HashSet :

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

Il y a plusieurs façons:

Initialisation des doubles accolades

C’est une technique qui crée une classe interne anonyme qui possède un initialiseur d’instance qui ajoute Ssortingng s à lui-même lorsqu’une instance est créée:

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

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

Une méthode utilitaire

L’écriture d’une méthode qui retourne un Set initialisé avec les éléments souhaités n’est pas trop difficile à écrire:

 public static Set newHashSet(Ssortingng... ssortingngs) { HashSet set = new HashSet(); for (Ssortingng s : ssortingngs) { set.add(s); } return set; } 

Le code ci-dessus permet uniquement l’utilisation d’une Ssortingng , mais il ne devrait pas être trop difficile d’autoriser 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 objects de collections.

Par exemple, Google Collections dispose d’une Sets.newHashSet(T...) qui remplira un HashSet avec des éléments d’un type spécifique.

Utilisation de Java 10 (ensembles non modifiables)

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

Utilisation de Java 9 (ensembles non modifiables)

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

Utilisation de Java 8 (ensembles modifiables)

Utiliser Stream dans Java 8.

 Set strSet1 = Stream.of("A", "B", "C", "D") .collect(Collectors.toCollection(HashSet::new)); // stream from an array (Ssortingng[] ssortingngArray) Set strSet2 = Arrays.stream(ssortingngArray) .collect(Collectors.toCollection(HashSet::new)); // stream from a list (List ssortingngList) Set strSet3 = ssortingngList.stream() .collect(Collectors.toCollection(HashSet::new)); 

Utilisation de Java 8 (ensembles non modifiables)

Utiliser Collections.unmodifiableSet – Nous pouvons utiliser Collections.unmodifiableSet comme:

 Set strSet4 = Collections.unmodifiableSet(strSet1); 

Mais cela semble un peu maladroit et nous pouvons écrire notre propre collectionneur comme ceci:

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

Et puis l’utiliser comme:

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

Using Collectors.collectingAndThen – Une autre approche consiste à utiliser la méthode Collectors.collectingAndThen qui nous permet d’effectuer des transformations de finition supplémentaires:

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

Si nous nous intéressons uniquement à Set nous pouvons également utiliser Collectors.toSet() à la place de Collectors.toCollection(HashSet::new) .

Vous pouvez le faire en Java 6:

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

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

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

 Set h = Collections.singleton("a"); 

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

 Set SsortingngSet = Sets.newSet("a", "b", "c"); 

Avec Java 9, vous pouvez effectuer les opérations suivantes:

 Set.of("a", "b"); 

et vous obtiendrez un ensemble immuable contenant les éléments. Pour plus de détails, voir la documentation Oracle du jeu d’interfaces .

Une généralisation de la fonction utilitaire de réponse de coobird pour créer de nouveaux HashSet :

 public static  Set newHashSet(T... objs) { Set set = new HashSet(); for (T o : objs) { set.add(o); } return set; } 

L’une des manières les plus pratiques est d’utiliser la méthode générique Collections.addAll () , qui prend une collection et varargs:

 Set h = new HashSet(); Collections.addAll(h, "a", "b"); 

Si le type contenu de l’ensemble est une énumération, il existe une méthode de fabrication Java (depuis 1.5):

 Set MY_SET = EnumSet.of( MY_ENUM.value1, MY_ENUM.value2, ... ); 

Avec les collections Eclipse, il existe différentes manières d’initialiser un Set contenant les caractères ‘a’ et ‘b’ dans une seule déclaration. Eclipse Collections contient des conteneurs à la fois pour les types object et primitif. J’ai donc montré comment utiliser Set ou CharSet en plus des versions mutables, immuables, synchronisées et non modifiables des deux.

 Set set = Sets.mutable.with("a", "b"); HashSet hashSet = Sets.mutable.with("a", "b").asLazy().into(new HashSet()); Set synchronizedSet = Sets.mutable.with("a", "b").asSynchronized(); Set unmodifiableSet = Sets.mutable.with("a", "b").asUnmodifiable(); MutableSet mutableSet = Sets.mutable.with("a", "b"); MutableSet synchronizedMutableSet = Sets.mutable.with("a", "b").asSynchronized(); MutableSet unmodifiableMutableSet = Sets.mutable.with("a", "b").asUnmodifiable(); ImmutableSet immutableSet = Sets.immutable.with("a", "b"); ImmutableSet immutableSet2 = Sets.mutable.with("a", "b").toImmutable(); CharSet charSet = CharSets.mutable.with('a', 'b'); CharSet synchronizedCharSet = CharSets.mutable.with('a', 'b').asSynchronized(); CharSet unmodifiableCharSet = CharSets.mutable.with('a', 'b').asUnmodifiable(); MutableCharSet mutableCharSet = CharSets.mutable.with('a', 'b'); ImmutableCharSet immutableCharSet = CharSets.immutable.with('a', 'b'); ImmutableCharSet immutableCharSet2 = CharSets.mutable.with('a', 'b').toImmutable(); 

Eclipse Collections est compatible avec Java 5 – 8.

Note: Je suis un committer pour les collections Eclipse.

Un peu compliqué mais fonctionne à partir de Java 5:

 Set h = new HashSet(Arrays.asList(new Ssortingng[] { "a", "b" })) 

Utilisez une méthode d’assistance pour le rendre lisible:

 Set h = asSet ("a", "b"); public Set asSet(Ssortingng... values) { return new HashSet(java.util.Arrays.asList(values)); } 
 import com.google.common.collect.Sets; Sets.newHashSet("a", "b"); 

ou

 import com.google.common.collect.ImmutableSet; ImmutableSet.of("a", "b"); 

Juste une petite note, quelle que soit l’approche fine mentionnée ici, s’il s’agit d’une valeur par défaut qui n’est généralement pas modifiée (comme un paramètre par défaut dans une bibliothèque que vous créez), il est conseillé de suivre ce modèle. :

 // Initialize default values with the method you prefer, even in a static block // It's a good idea to make sure these defaults aren't modifiable private final static Set DEFAULT_VALUES = Collections.unmodifiableSet(...); private Set values = DEFAULT_VALUES; 

L’avantage dépend du nombre d’instances que vous créez de cette classe et de la probabilité que les valeurs par défaut soient modifiées.

Si vous décidez de suivre ce modèle, vous pouvez également choisir la méthode d’initialisation définie la plus lisible. Comme les micro-différences d’efficacité entre les différentes méthodes n’auront probablement pas d’importance, vous n’initialiserez l’appareil qu’une seule fois.

(moche) Initialisation du double support sans effets secondaires:

 Set a = new HashSet<>(new HashSet() {{ add("1"); add("2"); }}) 

Mais dans certains cas, si nous mentionnions que le fait de rendre les collections finales impossibles à détecter est une bonne odeur, cela pourrait être très utile:

 final Set a = Collections.unmodifiableSet(new HashSet(){{ add("1"); add("2"); }}) 

Avec le lancement de java9 et les méthodes d’usine, cela est possible d’une manière plus propre:

 Set set2 = Set.of("a", "b", "c"); 

En utilisant Java 8, nous pouvons créer HashSet comme HashSet :

 Stream.of("A", "B", "C", "D").collect(Collectors.toCollection(HashSet::new)); 

Et si nous voulons un ensemble non modifiable, nous pouvons créer une méthode utilitaire comme:

 public static > Collector> toImmutableSet(Supplier supplier) { return Collector.of( supplier, Set::add, (left, right) -> { left.addAll(right); return left; }, Collections::unmodifiableSet); } 

Cette méthode peut être utilisée comme:

  Stream.of("A", "B", "C", "D").collect(toImmutableSet(HashSet::new)); 

Ceci est une solution élégante:

 public static final  Set makeSet(@SuppressWarnings("unchecked") T... o) { return new HashSet() { private static final long serialVersionUID = -3634958843858172518L; { for (T x : o) add(x); } }; } 

Le modèle de générateur peut être utile ici. Aujourd’hui, j’ai eu le même problème. où j’avais besoin de définir des opérations de mutation pour me renvoyer une référence de l’object Set, afin que je puisse le transmettre au constructeur de la super classe afin qu’il puisse continuer à l’append à son tour en construisant une nouvelle SsortingngSetBuilder juste construit. La classe de générateur que j’ai écrite ressemble à ceci (dans mon cas, c’est une classe interne statique d’une classe externe, mais elle peut aussi être sa propre classe indépendante):

 public interface Builder { T build(); } static class SsortingngSetBuilder implements Builder> { private final Set set = new HashSet<>(); StringSetBuilder add(String pStr) { set.add(pStr); return this; } StringSetBuilder addAll(Set pSet) { set.addAll(pSet); return this; } @Override public Set build() { return set; } } 

Notez les addAll() et add() , qui correspondent aux contreparties Set de Set.add() et Set.addAll() . Notez enfin la méthode build() , qui renvoie une référence à l’ensemble que le générateur encapsule. La figure ci-dessous illustre comment utiliser ce générateur de set:

 class SomeChildClass extends ParentClass { public SomeChildClass(Ssortingng pStr) { super(new SsortingngSetBuilder().add(pStr).build()); } } class ParentClass { public ParentClass(Set pSet) { super(new SsortingngSetBuilder().addAll(pSet).add("my own str").build()); } } 

Peut utiliser un bloc statique pour l’initialisation:

 private static Set codes1= new HashSet(Arrays.asList(1, 2, 3, 4)); private static Set codes2 = new HashSet(Arrays.asList(5, 6, 7, 8)); private static Set h = new HashSet(); static{ h.add(codes1); h.add(codes2); }