Initialisation d'une ArrayList sur une ligne
Je voulais 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 refactorisé le code comme suit:
ArrayList<String> places = new ArrayList<String>(
Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Y a-t-il une meilleure façon de le faire?
30 answers
En Fait, probablement la "meilleure" façon d'initialiser le ArrayList
est la méthode que vous avez écrit, comme il n'a pas besoin de créer un nouveau List
, en quelque sorte:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
Le problème est qu'il y a un peu de frappe nécessaire pour se référer à cette instance list
.
Il existe des alternatives, telles que la création d'une classe interne anonyme avec un initialiseur d'instance (également connu sous le nom d '"initialisation à double accolade"):
ArrayList<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Cependant, je n'aime pas trop cette méthode parce que ce que vous finissez avec est une sous-classe de ArrayList
qui a un initialiseur d'instance, et cette classe est créée juste pour créer un objet that cela me semble un peu exagéré.
Ce qui aurait été bien, c'est si la proposition Collection Literalspour Project Coin était acceptée (elle devait être introduite dans Java 7, mais elle ne devrait pas non plus faire partie de Java 8.):
List<String> list = ["A", "B", "C"];
Malheureusement, cela ne vous aidera pas ici, car il initialisera un List
immuable plutôt que an ArrayList
, et de plus, il n'est pas encore disponible, s'il le sera un jour.
Ce serait plus simple si vous deviez simplement le déclarer comme un List
- doit-il être une 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 entraînera la levée d'une exception UnsupportedOperationException
).
Pour faire une mutable liste qui est un béton 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"));
La réponse simple
Dans Java 9, ou plus tard, après List.of()
a été ajouté:
List<String> strings = List.of("foo", "bar", "baz");
Avec Java 10 ou version ultérieure, cela peut être raccourci avec le mot-clé var
.
var strings = List.of("foo", "bar", "baz");
Cela vous donnera une immuable List
, il ne peut donc pas être changé.
C'est ce que vous voulez dans la plupart des cas où vous le prépeuplez.
Java 8 ou version antérieure:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Cela vous donnera un List
soutenu par un tableau, donc il ne peut pas changer longueur.
Mais vous pouvez appeler List.set
, donc c'est toujours mutable.
Vous pouvez rendre Arrays.asList
encore plus court avec une importation statique:
List<String> strings = asList("foo", "bar", "baz");
L'importation statique:
import static java.util.Arrays.asList;
Que toutE 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 List.of
à of
, car cela devient déroutant.List.of
est déjà assez court et se lit bien.
En utilisant Stream
s
Pourquoi doit-il être un List
?
Avec Java 8 ou version ultérieure, vous pouvez utiliser un Stream
, qui est plus souple:
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, il suffit d'utiliser le Stream
, sans collecte à un List
.
{Si vous[62]}vraiment spécifiquement besoin d'un java.util.ArrayList
(Vous ne le faites probablement pas.)
Pour citer JEP 269 (emphase à moi):
Il existe un petit ensemble de cas d'utilisation pour initialiser une instance de collection mutable 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 deux préremplir un ArrayList
et ajouter par la suite (pourquoi?), utiliser
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
Ou en Java 8 ou plus tôt:
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 est préférable d'utiliser directement le Stream
au lieu de le collecter dans un List
.
Programme aux interfaces, pas aux implémentations
Vous avez dit que vous avez 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 le plus interface générale que vous allez utiliser (par exemple Iterable
, Collection
, ou List
), et initialisez-les 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 changer quand vous le souhaitez.
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 serait toujours de déclarer une variable an InputStream
même si elle est généralement un FileInputStream
ou un BufferedInputStream
, car bientôt, vous ou quelqu'un d'autre voudrez utiliser un autre type de InputStream
.
Si vous avez besoin d'une liste simple 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");
Avec Goyave, vous pouvez écrire:
ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");
Dans Goyave, il existe également d'autres constructeurs statiques utiles. Vous pouvez lire à leur sujet ici.
Avec java-9 et au-dessus, comme suggéré dans JEP 269: Convenience Factory Methods for Collections, cela pourrait être réalisé en utilisant collection literals maintenant avec -
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 à Collection de Littéraux proposition comme indiqué par @coobird. Clarifié également dans le PEC-
Solutions de rechange
Les changements de langue ont été pris en compte plusieurs fois, et rejeté:
Projet de pièce de monnaie, 29 mars 2009
Projet de pièce de monnaie, 30 mars 2009
JEP 186 discussion sur lambda-dev, janvier-mars 2014
La langue les propositions ont été mises de côté de préférence à une proposition basée sur la bibliothèque comme résumé dans ce message.
Related: Quel est l'intérêt des méthodes d'usine de commodité surchargées pour les Collections dans Java 9
Les littéraux de collection ne sont pas entrés dans Java 8, mais il est possible d'utiliser l'API Stream pour initialiser une liste dans une ligne assez 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");
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;
}
En Java 9, nous pouvons facilement initialiser un ArrayList
en 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 la Liste.de et de Tableaux.asList?
À propos de la façon la plus compacte de le faire est:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
Utilisez simplement le code ci-dessous comme suit.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
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 de même avec des ensembles et des 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 committer pour les collections Eclipse.
Voici une autre façon:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
(Devrait être un commentaire, mais trop long, donc nouvelle réponse). Comme d'autres l'ont mentionné, la méthode Arrays.asList
est de taille fixe, mais ce n'est pas le seul problème avec elle. Il ne gère pas non plus très bien l'héritage. Par exemple, supposons que vous ayez ce qui suit:
class A{}
class B extends A{}
public List<A> getAList(){
return Arrays.asList(new B());
}
Ce qui précède entraîne une erreur du compilateur, car List<B>
(qui est ce qui est renvoyé par les tableaux.asList) n'est pas une sous-classe de List<A>
, même si vous pouvez ajouter des objets de type B à un objet List<A>
. Pour contourner 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, esp. si vous avez besoin d'une liste illimitée ou que vous devez utiliser l'héritage.
Vous pouvez utiliser les instructions ci-dessous:
Extrait de code:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
Comme Tom a dit:
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 vous plaindre de "performance".
Dans ce cas, cela n'a pas de sens pour moi, pourquoi, puisque votre liste est prédéfinie, elle n'a pas été définie comme un tableau (puisque la 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 une 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 aussi 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
, qui nécessiterait une re-compilation si la liste devait être modifiée à l'avenir.
enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}
Serait devenir:
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 Enum ont une méthode statique values
qui renvoie un tableau contenant toutes les valeurs de l'énumération dans l'ordre dans lequel elles sont 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 bonne façon d'utiliser la méthode utilitaire statique Collections.addAll .
Java 9 a la méthode suivante pour créer un immuable liste:
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"));
Méthodes Similaires sont disponibles pour les Set
et Map
.
List<String> names = Arrays.asList("2","@2234","21","11");
Oui, avec l'aide de Tableaux vous pouvez initialiser la liste en une seule ligne,
List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");
Vous pouvez utiliser StickyList
à partir de Cactoos:
List<String> names = new StickyList<>(
"Scott Fitzgerald", "Fyodor Dostoyevsky"
);
Essayez avec cette ligne de code:
Collections.singletonList(provider)
En Java, vous ne pouvez pas faire
ArrayList<String> places = new ArrayList<String>( Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
Comme cela a été souligné, vous devrez faire une double initialisation d'accolade:
List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};
Mais cela peut vous forcer à ajouter une annotation @SuppressWarnings("serial")
ou à générer un UUID série qui est ennuyeux. De plus, la plupart des formateurs de code déballeront cela en plusieurs instructions/lignes.
Alternativement, vous pouvez faire
List<String> places = Arrays.asList(new String[] {"x", "y" });
, Mais alors vous voudrez peut-être faire un @SuppressWarnings("unchecked")
.
Toujours selon javadoc, vous devriez pouvoir le faire:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Mais je ne suis pas capable de le faire compiler avec JDK 1.6.
Collections.singletonList(messageBody)
Si vous auriez besoin d'avoir une liste de un élément de!
Les collections proviennent de java.util paquet.
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 qui peut avoir autant d'éléments que vous le souhaitez et appelez-la pour les ajouter en une seule ligne.
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.
Pour moi Tableaux.asList () est le meilleur et pratique. J'aime toujours initialiser cette façon. Si vous êtes un débutant dans les collections Java, j'aimerais que vous référiez à ArrayList initialization
Pourquoi ne pas créer une simple fonction utilitaire qui fait cela?
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");
fait intéressant, personne-liner avec l'autre surchargé Stream::collect
la méthode est listée
ArrayList<String> places = Stream.of( "Buenos Aires", "Córdoba", "La Plata" ).collect( ArrayList::new, ArrayList::add, ArrayList::addAll );
En fait, il est possible de le faire en une seule ligne:
Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})