Je dois créer un Set
avec des valeurs initiales.
Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");
Existe-t-il un moyen de faire cela en une seule ligne de code ? Par exemple, c'est utile pour un champ statique final.
Je dois créer un Set
avec des valeurs initiales.
Set<String> h = new HashSet<String>();
h.add("a");
h.add("b");
Existe-t-il un moyen de faire cela en une seule ligne de code ? Par exemple, c'est utile pour un champ statique final.
Il existe une sténographie que j'utilise et qui n'est pas très efficace en termes de temps, mais qui tient sur une seule ligne :
Set<String> h = new HashSet<>(Arrays.asList("a", "b"));
Encore une fois, cette méthode n'est pas efficace puisque vous construisez un tableau, le convertissez en une liste et utilisez cette liste pour créer un ensemble.
Lorsque j'initialise des ensembles finaux statiques, je l'écris généralement 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.
Bien qu'il soit très probablement correct au moment de l'écriture, à partir de Java 7, il faut utiliser l'opérateur Diamant comme dans : Set<String> h = new HashSet<>(Arrays.asList("a", "b")) ; public static final Set<String> MY_SET = new HashSet<>(Arrays.asList(SET_VALUES)) ;
Corrigé pour la notation en diamant de Java comme vous l'avez mentionné, mais je n'ai pas eu le temps de le tester. Si quelqu'un peut faire une double vérification, ce serait génial. La principale préoccupation est l'affectation de hashset à set, le constructeur de HashSet peut avoir besoin d'un type générique explicite.
@Gennadiy Je peux confirmer que la notation en diamant fonctionne bien (même à travers la déclaration Set et l'affectation HashSet).
Les littéraux de collection étaient prévus pour Java 7, mais n'y sont pas parvenus. Donc rien d'automatique pour le moment.
Vous pouvez utiliser la goyave Sets
:
Sets.newHashSet("a", "b", "c")
Ou vous pouvez utiliser la syntaxe suivante, qui créera une classe anonyme, mais c'est un peu compliqué :
Set<String> h = new HashSet<String>() {{
add("a");
add("b");
}};
@DD c'est un hack parce qu'il crée une sous-classe interne anonyme de HashSet avec une section d'initialisation statique qui appelle la méthode add(), ce qui est définitivement excessif pour cette situation. J'adore !
L'initialisation par double accolade est un hack très dangereux. La classe anonyme a un lien implicite avec la classe externe, ce qui peut entraîner des fuites de mémoire. Celui qui détient l'ensemble initialisé par la double accolade détient également la classe dans laquelle l'ensemble a été créé.
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 le JDK 8, cette méthode renvoie une valeur HashSet
La spécification ne le garantit pas, et cela pourrait changer à l'avenir. Si vous souhaitez spécifiquement un HashSet
faites ceci à la place :
Set<String> set = Stream.of("a", "b")
.collect(Collectors.toCollection(HashSet::new));
C'est encore plus verbeux et inutilement complexe que le bon vieux code de la question initiale.
@Natix Pour 2 éléments c'est plus verbeux, mais cette représentation commence à devenir concise si vous devez coder en dur l'ensemble avec plus d'éléments(10-100s)
Il y a plusieurs façons :
Initialisation de l'accolade double
Il s'agit d'une technique qui crée une classe interne anonyme dont l'initialisateur d'instance ajoute String
à lui-même lorsqu'une instance est créée :
Set<String> s = new HashSet<String>() {{
add("a");
add("b");
}}
Gardez à l'esprit que cela créera en fait une nouvelle sous-classe de HashSet
chaque fois qu'elle est utilisée, même si l'on ne doit pas écrire explicitement une nouvelle sous-classe.
Une méthode d'utilité
L'écriture d'une méthode qui renvoie un Set
qui est initialisé avec les éléments désiré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'une String
mais il ne devrait pas être trop difficile de permettre l'utilisation de tout type en utilisant des génériques.
Utiliser une bibliothèque
De nombreuses bibliothèques disposent d'une méthode pratique pour initialiser les objets de la collection.
Par exemple, Collections Google a un Sets.newHashSet(T...)
qui remplira un HashSet
avec des éléments d'un type spécifique.
GoogleCollections a également ImmutableSet.of(T...)
. La plupart du temps, lorsque vous faites cela, vous n'avez pas besoin de modifier à nouveau l'ensemble plus tard, et dans ce cas, l'utilisation d'un ensemble immuable présente de nombreux avantages.
Pour clarifier créera une nouvelle sous-classe de HashSet à chaque fois qu'elle sera utilisée. signifie "chaque fois qu'il est codé ". Chaque exécution fait pas créer une nouvelle sous-classe.
Ah. Il est probablement utile de noter que vous pouvez toujours ajouter des éléments à un ensemble final. Déclarez simplement l'ensemble final, mais ajoutez des éléments dans le constructeur (ou n'importe où ailleurs) comme vous le feriez normalement. Des éléments peuvent être ajoutés ou supprimés dans une collection finale. Seule la référence à la collection elle-même est finale.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
Pour Java 8, Java 9 et Java 10, consultez ma réponse. stackoverflow.com/a/37406054/1216775
2 votes
La réponse de Michael Berdyshev est en fait la meilleure, car c'est la façon la plus propre de produire un modifiable Set. i_am_zero Answer dispose également d'une autre méthode pour créer un Set modifiable, mais elle est plus verbeuse/clastique [utilisation du streaming Lambda] ; sinon, i_am_zero Answer est le meilleur choix pour l'étendue de ses différentes options (à travers les versions de Java).
0 votes
NOTE : Certaines réponses omettent le paramètre `new HashSet<T>(int initialCapacity), si vous connaissez déjà la taille de la collection, utilisez-le.