Vraag Initialisatie van een ArrayList op één regel


Ik wil een lijst met opties voor testdoeleinden maken. In eerste instantie deed ik dit:

ArrayList<String> places = new ArrayList<String>();
places.add("Buenos Aires");
places.add("Córdoba");
places.add("La Plata");

Vervolgens heb ik de code als volgt opnieuw geformuleerd:

ArrayList<String> places = new ArrayList<String>(
    Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

Is er een betere manier om dit te doen?


2157
2018-06-17 04:10


oorsprong


antwoorden:


Waarschijnlijk de "beste" manier om het te initialiseren ArrayList is de methode die je hebt geschreven, omdat er geen nieuwe hoeft te worden gemaakt List In elk geval:

ArrayList<String> list = new ArrayList<String>();
list.add("A");
list.add("B");
list.add("C");

De vangst is dat er nogal wat typen is vereist om daarnaar te verwijzen list aanleg.

Er zijn alternatieven, zoals het maken van een anonieme inner klasse met een instantie-initialisatie (ook bekend als een "double brace initialization"):

ArrayList<String> list = new ArrayList<String>() {{
    add("A");
    add("B");
    add("C");
}};

Ik ben echter niet zo gek op die methode, want waar je uiteindelijk mee komt is een subklasse van ArrayList die een instantie-initializer heeft, en die klasse is gemaakt om slechts één object te maken - dat lijkt mij gewoon een beetje overdreven.

Wat zou leuk geweest zijn was als het Collection Literals-voorstel voor Project Coin werd geaccepteerd (het was gepland om te worden geïntroduceerd in Java 7, maar het is ook niet waarschijnlijk dat het deel uitmaakt van Java 8.):

List<String> list = ["A", "B", "C"];

Helaas zal het je hier niet helpen, omdat het een onveranderlijk zal initialiseren List in plaats van een ArrayListen bovendien is het nog niet beschikbaar, als het dat ooit zal zijn.


1624
2018-06-17 04:13



Het zou eenvoudiger zijn als je het gewoon zou verklaren als een List - Moet het een ArrayList zijn?

List<String> places = Arrays.asList("Buenos Aires", "Córdoba", "La Plata");

Of als u slechts één element heeft:

List<String> places = Collections.singletonList("Buenos Aires");

Dit zou dat betekenen places is onveranderlijk (proberen te veranderen zal leiden tot een UnsupportedOperationException uitzondering om te worden gegooid).

Om een ​​veranderlijke lijst te maken die concreet is ArrayList je kunt een maken ArrayList van de onveranderlijke lijst:

ArrayList<String> places = new ArrayList<>(Arrays.asList("Buenos Aires", "Córdoba", "La Plata"));

1725
2018-06-17 04:15



Het simpele antwoord

In Java 8 of eerder:

List<String> strings = Arrays.asList("foo", "bar", "baz");

Dit geeft je een List ondersteund door de array, dus het kan de lengte niet veranderen.
Maar je kunt bellen List.set, dus het is nog steeds veranderlijk.


In Java 9:

List<String> strings = List.of("foo", "bar", "baz");

Dit geeft je een onveranderlijk List, dus het kan niet worden veranderd.
Dat is wat je wilt in de meeste gevallen waar je het prepopuleert.


Het kortere antwoord

Je kunt maken Arrays.asList nog korter met een statische import:

List<String> strings = asList("foo", "bar", "baz");

De statische import:

import static java.util.Arrays.asList;  

Welke moderne IDE u zal voorstellen en automatisch voor u zal doen.
Bijvoorbeeld in IntelliJ IDEA drukt u op Alt+Enter en selecteer Static import method....


Ik raad echter af om de Java 9 te verkorten List.of methode, omdat het gewoon zo is of wordt verwarrend.
List.of is al kort genoeg en leest goed.


Gebruik makend van Streams

Waarom moet het een zijn? List?
Met Java 8 of hoger kunt u een Stream wat flexibeler is:

Stream<String> strings = Stream.of("foo", "bar", "baz");

U kunt aaneenschakelen Streams:

Stream<String> strings = Stream.concat(Stream.of("foo", "bar"),
                                       Stream.of("baz", "qux"));

Of je kunt gaan vanaf een Stream naar een List:

List<String> strings = Stream.of("foo", "bar", "baz").collect(toList());

Maar gebruik bij voorkeur gewoon de Stream zonder het te verzamelen naar a List.


als jij werkelijk specifiek nodig a java.util.ArrayList

(Waarschijnlijk niet.)
Om te citeren JEP 269 (nadruk van mij):

Er is een kleine set van gebruiksgevallen voor het initialiseren van een veranderlijk verzamelingsinstantie met een vooraf gedefinieerde reeks waarden. Het heeft gewoonlijk de voorkeur om die vooraf gedefinieerde waarden in een onveranderlijke verzameling te hebben en vervolgens om de veranderbare verzameling via een kopieconstructor te initialiseren.


Als je wilt beide prepopulate een ArrayList  en voeg er achteraf aan toe (waarom?), gebruik

List<String> strings = new ArrayList<>(asList("foo", "bar", "baz"));

of in Java 9:

List<String> strings = new ArrayList<>(List.of("foo", "bar", "baz"));

of gebruiken Stream:

List<String> strings = Stream.of("foo", "bar", "baz")
                             .collect(toCollection(ArrayList::new));

Maar nogmaals, het is beter om gewoon de Stream rechtstreeks in plaats van het te verzamelen naar een List.


Programmeer naar interfaces, niet naar implementaties

U zei dat u de lijst als een hebt verklaard ArrayList in je code, maar dat zou je alleen moeten doen als je een lid gebruikt ArrayList dat is niet in List.

Wat je waarschijnlijk niet doet.

Gewoonlijk moet u gewoon variabelen declareren door de meest algemene interface die u gaat gebruiken (bijv. Iterable, Collectionof List) en initialiseer ze met de specifieke implementatie (bijv. ArrayList, LinkedList of Arrays.asList()).

Anders beperk je je code tot dat specifieke type en zal het moeilijker zijn om te veranderen wanneer je dat wilt.

Bijvoorbeeld:

// Iterable if you just need iteration, for (String s : strings):
Iterable<String> strings = new ArrayList<>();   

// Collection if you also need .size() or .stream():
Collection<String> strings = new ArrayList<>(); 

// List if you also need .get(index):
List<String> strings = new ArrayList<>();       

// Don't declare a specific list implementation
// unless you're sure you need it:
ArrayList<String> strings = new ArrayList<>();  // You don't need ArrayList

Een ander voorbeeld is altijd variabele verklaren InputStream ook al is het meestal een FileInputStream of a BufferedInputStream, omdat op een dag jij of iemand anders binnenkort een ander soort wilt gebruiken InputStream.


580
2017-09-09 12:33



Als u een eenvoudige lijst met maat 1 nodig heeft:

List<String> strings = new ArrayList<String>(Collections.singletonList("A"));

Als u een lijst met verschillende objecten nodig heeft:

List<String> strings = new ArrayList<String>();
Collections.addAll(strings,"A","B","C","D");

100
2017-08-30 04:33



Met guava je kan schrijven:

ArrayList<String> places = Lists.newArrayList("Buenos Aires", "Córdoba", "La Plata");

In Guava zijn er ook andere nuttige statische constructeurs. Je kunt erover lezen hier.


52
2017-07-29 13:24



Letterlijke verzamelingen kwamen niet in Java 8, maar het is mogelijk om de Stream API te gebruiken om een ​​lijst in een vrij lange regel te initialiseren:

List<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toList());

Als u ervoor moet zorgen dat uw List is een ArrayList:

ArrayList<String> places = Stream.of("Buenos Aires", "Córdoba", "La Plata").collect(Collectors.toCollection(ArrayList::new));

32
2018-04-03 23:21



import com.google.common.collect.ImmutableList;

....

List<String> places = ImmutableList.of("Buenos Aires", "Córdoba", "La Plata");

26
2018-05-12 13:14