Initialisation d'une ArrayList sur une ligne
-
05-07-2019 - |
Question
Je souhaite 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 façon de faire cela?
La solution
En fait, probablement le " meilleur " moyen d’initialiser la ArrayList
est la méthode que vous avez écrite, car il n’est pas nécessaire de créer un nouveau List
:
ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");
Le problème est qu’il faut pas mal de frappe pour se référer à cette list
instance.
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 obtenez une sous-classe de <=> qui a un initialiseur d'instance, et cette classe est créée uniquement pour créer un objet - cela ressemble à un peu exagéré pour moi.
Ce qui aurait été bien si les Littéraux de collection la proposition de Project Coin a été acceptée (elle devait être introduite dans Java 7, mais cela ne fera probablement pas partie de Java 8.):
List<String> list = ["A", "B", "C"];
Malheureusement, cela ne vous aidera pas ici, car il initialisera un <=> immuable plutôt qu'un <=>, et de plus, il n'est pas encore disponible, s'il le sera jamais.
Autres conseils
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 modifier provoquera la génération d'une exception UnsupportedOperationException
).
Pour créer une liste modifiable qui est concrète ArrayList
, vous pouvez créer un <=> à partir de la liste immuable:
ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));
La réponse simple
Sous Java 10, 11, 12 ou ultérieur:
var strings = List.of("foo", "bar", "baz");
Sous 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.
Java 8 ou version antérieure:
List<String> strings = Arrays.asList("foo", "bar", "baz");
Cela vous donnera un List.set
supporté par le tableau, il ne peut donc pas changer de longueur.
Mais vous pouvez appeler Arrays.asList
, il est donc toujours modifiable.
Vous pouvez rendre Alt+Enter
encore plus court avec une importation statique:
List<String> strings = asList("foo", "bar", "baz");
L'importation 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 Static import method...
et sélectionnez List.of
.
Cependant, je ne recommande pas de raccourcir la méthode Java 9 of
, car avoir juste Stream
devient déroutant.
java.util.ArrayList
est déjà assez court et lit bien.
Utilisation de ArrayList
s
Pourquoi faut-il que ce soit un Iterable
?
Avec Java 8 ou version ultérieure, vous pouvez utiliser un Collection
qui est plus flexible:
Stream<String> strings = Stream.of("foo", "bar", "baz");
Vous pouvez concaténer LinkedList
s:
Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
Stream.of("baz", "qux"));
Ou vous pouvez passer d'un Arrays.asList()
à un void method(...)
:
import static java.util.stream.Collectors.toList;
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());
Mais de préférence, utilisez simplement le InputStream
sans le collecter vers un FileInputStream
.
Si vous vraiment avez particulièrement besoin d'un BufferedInputStream
(Vous n'avez probablement pas.) 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 pré-remplir un ajout <=> et par la suite (pourquoi?), utilisez ou dans Java 8 ou une version antérieure: ou en utilisant <=>: Mais encore une fois, il vaut mieux utiliser le <=> directement plutôt que de le collecter dans un <=>. Vous avez dit que vous avez déclaré la liste comme <=> dans votre code, mais vous ne devriez le faire que si vous utilisez un membre de <=> qui n'est pas dans <=>. Ce que vous ne ferez probablement pas. Habituellement, vous devez simplement déclarer les variables à l'aide de l'interface la plus générale que vous allez utiliser (par exemple, <=>, <=> ou <=>), puis les initialiser avec une implémentation spécifique (par exemple, <=>, < => ou <=>). Sinon, vous limitez votre code à ce type spécifique et il sera plus difficile de le modifier si vous le souhaitez. Par exemple, si vous passez un <=> à un <=>: Un autre exemple consisterait toujours à déclarer une variable <=> même s’il s’agit en général de <=> ou de <=>, car dans un jour prochain, vous ou une autre personne voudrez utiliser un autre type de <=>.
Pour citer PPC 269 (
ArrayList<String> strings = new ArrayList<>(List.of("foo", "bar"));
strings.add("baz");
ArrayList<String> strings = new ArrayList<>(asList("foo", "bar"));
strings.add("baz");
import static java.util.stream.Collectors.toCollection;
ArrayList<String> strings = Stream.of("foo", "bar")
.collect(toCollection(ArrayList::new));
strings.add("baz");
Programmez les interfaces et non les implémentations
// 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
}
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 n'ont pas été intégrés à Java 8, mais il est possible d'utiliser l'API Stream pour initialiser une liste sur 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 la proposition d'amélioration du JDK - 269 , cela pourrait être réalisé en utilisant les littéraux de collection maintenant -
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 de collection Literals comme l'a déclaré @coobird également. De plus amples précisions dans le doc du PEC également -
Alternatives
Les modifications de langue ont été examinées à plusieurs reprises et rejetées:
Proposition de pièce de monnaie, 29 mars 2009
Proposition de pièce de monnaie, 30 mars 2009
Discussion sur le PEC 186 sur lambda-dev, janvier -Mars 2014
La langue propositions ont été réservées de préférence à une proposition basée sur une bibliothèque résumées dans ce message.
Related = > Qu'est-ce que c'est? le point de surcharge des méthodes Convenience Factory pour les collections en Java 9
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 List.of et Arrays.asList?
Avec les Collections Eclipse , vous pouvez écrire ce qui suit:
List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
Vous pouvez également préciser les types et déterminer 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 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 partisan des collections Eclipse.
La façon la plus compacte de procéder est la suivante:
Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);
Voici un autre moyen:
List<String> values = Stream.of("One", "Two").collect(Collectors.toList());
Utilisez simplement le code ci-dessous comme suit.
List<String> list = new ArrayList<String>() {{
add("A");
add("B");
add("C");
}};
Vous pouvez utiliser les instructions ci-dessous:
Extrait de code:
String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);
(Doit ê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. 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 génère 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 <=> 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 devez utiliser l'héritage.
Comme Tom a déclaré :
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 puisse vous amener à vous plaindre de "performance".
Dans ce cas, cela n’a aucun sens pour moi, 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 enum
ensemble, ce qui nécessiterait une nouvelle compilation si la liste devait être modifiée à l'avenir.
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 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 présenté un autre moyen intéressant d'utiliser la méthode de l'utilitaire statique Collections.addAll .
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
.
List<String> names = Arrays.asList("2","@2234","21","11");
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)
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 cela a été souligné, vous devez effectuer une initialisation à double accolade:
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. De plus, 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 un @SuppressWarnings("unchecked")
.
Selon javadoc, vous devriez également pouvoir le faire:
List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");
Mais je ne parviens pas à le compiler avec JDK 1.6.
Collections.singletonList(messageBody)
Si vous devez disposer d'une liste d'un élément !
LesCollections proviennent du package java.util .
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.
Voici le code généré 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 & # 65306; Je suis le développeur de AbacusUtil.
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 les collections Java, j'aimerais que vous vous référiez à Initialisation ArrayList .
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");
Je crée une liste de messageTemplate à partir d'un fichier XML stocké dans le chemin path précédent dans un contexte statique
public final class TemplateStore {
private TemplateStore(){}
private static final String [] VERSIONS = {"081"};
private static final String TEMPLATE_FILE_MASK = "template/EdiTemplates_v%s.xml";
private static final String ERROR = "Error In Building Edifact Message Template Store";
public static final List<MessageTemplate> TEMPLATE_LIST = Arrays.stream(VERSIONS)
.map(version -> TemplateStore.class
.getClassLoader().getResourceAsStream(String.format(TEMPLATE_FILE_MASK, version)))
.map(inputStream -> {
try {
return ((EdiTemplates) JAXBContext.newInstance(EdiTemplates.class).createUnmarshaller()
.unmarshal(inputStream)).getMessageTemplate();
} catch (JAXBException e) {
throw new IllegalArgumentException(ERROR, e);
}})
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
En fait, il est possible de le faire en une seule ligne:
Arrays.asList(new MyClass[] {new MyClass("arg1"), new MyClass("arg2")})