Je veux créer une liste d'options à des fins de test. Au début, j'ai fait ceci:
ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");
Ensuite, j'ai refactoré le code comme suit:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Y a-t-il une meilleure manière de faire cela?
En fait, le "meilleur" moyen d'initialiser la ArrayList
est probablement la méthode que vous avez écrite, car il n'est pas nécessaire de créer une nouvelle List
:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
Le problème, c'est qu'il faut pas mal de dactylographie pour faire référence à cette instance list
.
Il existe des alternatives, telles que la création d'une classe interne anonyme avec un initialiseur d'instance (également appelée "initialisation à double accolade"):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Cependant, je n'aime pas trop cette méthode, car vous vous retrouvez avec une sous-classe de ArrayList
qui a un initialiseur d'instance, et cette classe est créée uniquement pour créer un objet - cela semble être un peu un peu exagéré pour moi.
Qu'aurait été Nice si la proposition de collection Literals pour Project Coin était acceptée (elle devait être introduite dans Java 7, mais ce n'est pas le cas susceptibles de faire partie de Java 8 non plus.):
List<String> list = ["A", "B", "C"];
Malheureusement, cela ne vous aidera pas ici, car il initialisera un List
immuable plutôt qu'un ArrayList
, et de plus, il n'est pas encore disponible, si jamais il le sera.
Ce serait plus simple si vous deviez simplement le déclarer comme un List
- faut-il que ce soit un ArrayList?
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Ou si vous n'avez qu'un seul élément:
List<String> places = Collections.singletonList("Buenos Aires");
Cela signifierait que places
est immuable (essayer de le changer provoquera la levée d'une exception UnsupportedOperationException
).
Pour créer une liste modifiable concrète ArrayList
, vous pouvez créer un ArrayList
à partir de la liste immuable:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Dans Java 10, 11, 12 ou version ultérieure:
var strings = List.of("foo", "bar", "baz");
Dans Java 9 ou version ultérieure:
List<String> strings = List.of("foo", "bar", "baz");
Cela vous donnera un List
immuable, donc il ne peut pas être changé.
C’est ce que vous voulez dans la plupart des cas où vous le pré-remplissez.
List<String> strings = Arrays.asList("foo", "bar", "baz");
Cela vous donnera un List
sauvegardé par le tableau, donc il ne peut pas changer de longueur.
Mais vous pouvez appeler List.set
, il est donc toujours modifiable.
Vous pouvez rendre Arrays.asList
encore plus court avec une importation statique:
List<String> strings = asList("foo", "bar", "baz");
L'import statique:
import static Java.util.Arrays.asList;
Ce que tout IDE moderne suggérera et fera automatiquement pour vous.
Par exemple, dans IntelliJ IDEA, vous appuyez sur Alt+Enter
et sélectionnez Static import method...
.
Cependant, je ne recommande pas de raccourcir la méthode Java 9 List.of
, car le simple fait de of
devient déroutant.List.of
est déjà suffisamment court et lit bien.
Stream
sPourquoi faut-il que ce soit un List
?
Avec Java 8 ou version ultérieure, vous pouvez utiliser un Stream
qui est plus flexible:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Vous pouvez concaténer Stream
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Ou vous pouvez passer d'un Stream
à un List
:
import static Java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Mais de préférence, utilisez simplement la Stream
sans la collecter dans un List
.
Java.util.ArrayList
(Vous n'avez probablement pas.)
Pour citer JEP 269 (souligné par moi):
Il existe un petit ensemble de cas d'utilisation permettant d'initialiser une instance de collection modifiable avec un ensemble prédéfini de valeurs. Il est généralement préférable que ces valeurs prédéfinies soient dans une collection immuable, puis d'initialiser la collection mutable via un constructeur de copie.
Si vous voulez les deux pré-remplir une ArrayList
et y ajouter par la suite (pourquoi?), Utilisez
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
ou dans Java 8 ou version antérieure:
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
ou en utilisant Stream
:
import static Java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Mais encore une fois, il vaut mieux utiliser directement la Stream
au lieu de la collecter dans un List
.
Vous avez déclaré que vous aviez déclaré la liste en tant que ArrayList
dans votre code, mais vous ne devriez le faire que si vous utilisez un membre de ArrayList
qui n'est pas dans List
.
Ce que vous ne faites probablement pas.
Habituellement, vous devez simplement déclarer les variables par l’interface la plus générale que vous allez utiliser (par exemple, Iterable
, Collection
ou List
), et les initialiser avec l’implémentation spécifique (par exemple, ArrayList
, LinkedList
ou Arrays.asList()
).
Sinon, vous limitez votre code à ce type spécifique et il sera plus difficile de le modifier à tout moment.
Par exemple, si vous passez un ArrayList
à un void method(...)
:
// Iterable if you just need iteration, for (String s : strings):
void method(Iterable<String> strings) {
for (String s : strings) { ... }
}
// Collection if you also need .size(), .isEmpty(), or .stream():
void method(Collection<String> strings) {
if (!strings.isEmpty()) { strings.stream()... }
}
// List if you also need .get(index):
void method(List<String> strings) {
strings.get(...)
}
// Don't declare a specific list implementation
// unless you're sure you need it:
void method(ArrayList<String> strings) {
??? // You don't want to limit yourself to just ArrayList
}
Un autre exemple consisterait toujours à déclarer une variable InputStream
même s’il s’agit généralement d’un FileInputStream
ou d'un BufferedInputStream
, car un jour, vous ou une autre personne voudrez utiliser un autre type de InputStream
.
Si vous avez besoin d’une simple liste de taille 1:
List<String> strings = new ArrayList<String>(Collections.singletonList("A"));
Si vous avez besoin d'une liste de plusieurs objets:
List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");
Les littéraux de collection ne se trouvaient pas dans Java 8, mais il est possible d'utiliser l'API Stream pour initialiser une liste dans une ligne plutôt longue:
List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());
Si vous devez vous assurer que votre List
est un ArrayList
:
ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));
import com.google.common.collect.ImmutableList;
....
List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
Avec Java 9
, comme suggéré dans Proposition d'amélioration JDK - 269 , ceci pourrait être réalisé à l'aide de littéraux de collection maintenant comme -
List<String> list = List.of("A", "B", "C");
Set<String> set = Set.of("A", "B", "C");
Une approche similaire s'appliquerait également à Map
Map<String, String> map = Map.of("k1", "v1", "k2", "v2", "k3", "v3")
qui est similaire à proposition Collection Literals , comme l'a également déclaré @coobird. Le doc du PEC précise également -
Alternatives
Les changements de langue ont été examinés à plusieurs reprises et rejetés:
Proposition de pièce de monnaie, 29 mars 2009
Proposition de pièce de monnaie, 30 mars 2009
Discussion du PEC 186 sur lambda-dev, janvier-mars 2014
Les propositions de langue ont été mises de côté de préférence à une proposition basée sur une bibliothèque, comme résumé dans ce message.
Vous pouvez créer une méthode d'usine:
public static ArrayList<String> createArrayList(String ... elements) {
ArrayList<String> list = new ArrayList<String>();
for (String element : elements) {
list.add(element);
}
return list;
}
....
ArrayList<String> places = createArrayList(
"São Paulo", "Rio de Janeiro", "Brasília");
Mais ce n'est pas beaucoup mieux que votre premier refactoring.
Pour plus de flexibilité, il peut être générique:
public static <T> ArrayList<T> createArrayList(T ... elements) {
ArrayList<T> list = new ArrayList<T>();
for (T element : elements) {
list.add(element);
}
return list;
}
Dans Java 9, nous pouvons facilement initialiser un ArrayList
sur une seule ligne:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
ou
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Cette nouvelle approche de Java 9 présente de nombreux avantages par rapport aux précédentes:
Voir ce post pour plus de détails -> Quelle est la différence entre List.of et Arrays.asList?
Avec Eclipse Collections , vous pouvez écrire ce qui suit:
List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
Vous pouvez également être plus précis sur les types et s'ils sont mutables ou immuables.
MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Vous pouvez également faire la même chose avec Ensembles et Sacs:
Set<String> set = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableSet<String> mSet = Sets.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet<String> iSet = Sets.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Bag<String> bag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
MutableBag<String> mBag = Bags.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableBag<String> iBag = Bags.immutable.with("Buenos Aires", "Córdoba", "La Plata");
Remarque: Je suis un partisan des collections Eclipse.
Utilisez simplement le code ci-dessous comme suit.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Voici un autre moyen:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
La manière la plus compacte de procéder est la suivante:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
(Devrait être un commentaire, mais trop long, donc nouvelle réponse). Comme d'autres l'ont mentionné, la méthode Arrays.asList
a une taille fixe, mais ce n'est pas le seul problème. De plus, il ne gère pas très bien l'héritage. Par exemple, supposons que vous ayez les éléments suivants:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
Ce qui précède entraîne une erreur de compilation, car List<B>
(qui est renvoyé par Arrays.asList) n'est pas une sous-classe de List<A>
, même si vous pouvez ajouter des objets de type B à un List<A>
objet. Pour résoudre ce problème, vous devez faire quelque chose comme:
new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))
C’est probablement la meilleure façon de procéder, en particulier. si vous avez besoin d'une liste illimitée ou avez besoin d'utiliser l'héritage.
Vous pouvez utiliser les déclarations ci-dessous:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
Java 9 utilise la méthode suivante pour créer une liste immuable:
List<String> places = List.of("Buenos Aires", "Córdoba", "La Plata");
qui est facilement adapté pour créer une liste mutable, si nécessaire:
List<String> places = new ArrayList<>(List.of("Buenos Aires", "Córdoba", "La Plata"));
Des méthodes similaires sont disponibles pour Set
et Map
.
Comme dit Tom :
List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");
Mais puisque vous vous êtes plaint de vouloir une ArrayList, vous devez d’abord savoir que ArrayList est une sous-classe de List et vous pouvez simplement ajouter cette ligne:
ArrayList<String> myPlaces = new ArrayList(places);
Bien que, cela pourrait vous faire plaindre de "performance".
Dans ce cas, cela n’a aucun sens pour moi, car, puisque votre liste est prédéfinie, elle n’a pas été définie comme un tableau (car sa taille est connue au moment de l’initialisation). Et si c'est une option pour vous:
String[] places = {"Buenos Aires", "Córdoba", "La Plata"};
Si vous ne vous souciez pas des différences de performances mineures, vous pouvez également copier un tableau dans un ArrayList très simplement:
ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));
D'accord, mais à l'avenir, vous avez besoin d'un peu plus que le nom du lieu, vous avez également besoin d'un code de pays. En supposant qu'il s'agisse toujours d'une liste prédéfinie qui ne changera jamais pendant l'exécution, il convient d'utiliser un ensemble enum
, ce qui nécessiterait une nouvelle compilation si la liste devait être modifiée ultérieurement.
enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}
deviendrait:
enum Places {
BUENOS_AIRES("Buenos Aires",123),
CORDOBA("Córdoba",456),
LA_PLATA("La Plata",789);
String name;
int code;
Places(String name, int code) {
this.name=name;
this.code=code;
}
}
Les énumérations ont une méthode statique values
qui renvoie un tableau contenant toutes les valeurs de l’énum dans l’ordre dans lequel elles ont été déclarées, par exemple:
for (Places p:Places.values()) {
System.out.printf("The place %s has code %d%n",
p.name, p.code);
}
Dans ce cas, je suppose que vous n’auriez pas besoin de votre ArrayList.
P.S. Randyaa a démontré une autre manière agréable d'utiliser la méthode de l'utilitaire statique Collections.addAll .
List<String> names = Arrays.asList("2","@2234","21","11");
Vous pouvez utiliser StickyList
de Cactoos :
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
Essayez avec cette ligne de code:
Collections.singletonList(provider)
Oui, à l’aide de tableaux, vous pouvez initialiser la liste de tableaux sur une ligne,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
En Java, vous ne pouvez pas faire
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Comme il a été souligné, vous devez effectuer une initialisation à double attache:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
Mais cela peut vous obliger à ajouter une annotation @SuppressWarnings("serial")
ou à générer un UUID série ennuyeux. En outre, la plupart des formateurs de code décompressent cela en plusieurs instructions/lignes.
Sinon, vous pouvez faire
List<String> places = Arrays.asList(new String[] {"x", "y" });
mais alors vous voudrez peut-être faire une @SuppressWarnings("unchecked")
.
Toujours selon javadoc, vous devriez pouvoir le faire:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Mais je ne parviens pas à le compiler avec JDK 1.6.
La meilleure façon de le faire:
package main_package;
import Java.util.ArrayList;
public class Stackkkk {
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<Object>();
add(list, "1", "2", "3", "4", "5", "6");
System.out.println("I added " + list.size() + " element in one line");
}
public static void add(ArrayList<Object> list,Object...objects){
for(Object object:objects)
list.add(object);
}
}
Créez simplement une fonction pouvant contenir autant d'éléments que vous le souhaitez et appelez-la pour les ajouter sur une seule ligne.
Collections.singletonList(messageBody)
Si vous avez besoin d'une liste de n élément!
Les collections proviennent du package Java.util .
Voici le code par AbacusUtil
// ArrayList
List<String> list = N.asList("Buenos Aires", "Córdoba", "La Plata");
// HashSet
Set<String> set = N.asSet("Buenos Aires", "Córdoba", "La Plata");
// HashMap
Map<String, Integer> map = N.asMap("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// Or for Immutable List/Set/Map
ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", "Córdoba", "La Plata");
ImmutableSet.of("Buenos Aires", 1, "Córdoba", 2, "La Plata", 3);
// The most efficient way, which is similar with Arrays.asList(...) in JDK.
// but returns a flexible-size list backed by the specified array.
List<String> set = Array.asList("Buenos Aires", "Córdoba", "La Plata");
Déclaration : Je suis le développeur de AbacusUtil.
Pourquoi ne pas créer une fonction utilitaire simple qui le fasse?
static <A> ArrayList<A> ll(A... a) {
ArrayList l = new ArrayList(a.length);
for (A x : a) l.add(x);
return l;
}
"ll
" signifie "liste littérale".
ArrayList<String> places = ll("Buenos Aires", "Córdoba", "La Plata");
Pour moi, Arrays.asList () est le meilleur et le plus pratique. J'aime toujours initialiser de cette façon. Si vous êtes débutant dans Java Collections, j'aimerais que vous vous référiez initialisation de ArrayList