Initialisatie van een ArrayList in één regel

Ik wilde een lijst met opties maken voor testdoeleinden. Eerst 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 aangepast:

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

Is er een betere manier om dit te doen?


Antwoord 1, autoriteit 100%

Eigenlijk is waarschijnlijk de “beste” manier om de ArrayListte initialiseren de methode die je hebt geschreven, omdat er op geen enkele manier een nieuwe Listhoeft te worden gemaakt:

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

Het probleem is dat er nogal wat getypt moet worden om naar die Listinstantie te verwijzen.

Er zijn alternatieven, zoals het maken van een anonieme binnenklasse met een instantie-initialisatie (ook bekend als een “dubbele accolade-initialisatie”):

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

Ik ben echter niet zo dol op die methode, want wat je uiteindelijk krijgt is een subklasse van ArrayListdie een instantie-initialisatiefunctie heeft, en die klasse is gemaakt om slechts één object te maken — dat lijkt me een beetje overdreven.

Het zou leuk geweest zijn als de Collection Literals voorstelvoor Project Coinwerd geaccepteerd (het was gepland om te worden geïntroduceerd in Java 7, maar het is waarschijnlijk ook geen onderdeel van Java 8.):

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

Helaas zal het je hier niet helpen, omdat het een onveranderlijke Listinitialiseert in plaats van een ArrayList, en bovendien is het nog niet beschikbaar, als het ooit zal gebeuren zijn.


Antwoord 2, autoriteit 98%

Het zou eenvoudiger zijn als je het gewoon zou declareren als een List– moet het een ArrayList zijn?

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

Of als je maar één element hebt:

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

Dit zou betekenen dat placesonveranderlijkis (proberen dit te wijzigen zal een UnsupportedOperationException-uitzondering veroorzaken).

Om een veranderlijke lijst te maken die een concrete ArrayListis, kun je een ArrayListmaken van de onveranderlijke lijst:

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

Antwoord 3, autoriteit 45%

Het simpele antwoord

Java 10 of hoger:

var strings = List.of("foo", "bar", "baz");

Dit geeft je een onveranderlijkeList, dus deze kan niet worden gewijzigd.
Dat is wat je wilt in de meeste gevallen waar je het vooraf invult.

Java 9

Als u Java 9gebruikt, kunt u het trefwoord varniet gebruiken:

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

Java 8 of eerder:

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

Dit geeft u een List*ondersteund door een array, zodat deze niet van lengte kan veranderen.
Maar je kunt List.set(...)aanroepen, dus het is nog steeds wijzigbaar.

*
Implementatiedetail: het is een privé geneste klasse binnen java.util.Arrays, genaamd ArrayList,
wat een andere klasse is dan java.util.ArrayList, ook al zijn hun eenvoudige namen hetzelfde.

Statische import

Je kunt Java 8 Arrays.asListnog korter maken met een statische import:

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

Elke moderne IDE*zal dit voor je voorstellen en doen.

Ik raad niet aan om de methode List.ofstatisch te importeren als alleen of, omdat dit verwarrend is.

*
In IntelliJ IDEA drukt u bijvoorbeeld op Alt+Enteren selecteert u Static import method...

Gebruik Streams

Waarom moet het een Listzijn?
Met Java 8 of hoger kunt u een Streamgebruiken die flexibeler is:

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

U kunt Streams samenvoegen:

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

Of je kunt van een Streamnaar een Listgaan:

import static java.util.stream.Collectors.toList;
...
var strings = Stream.of("foo", "bar", "baz").toList(); // Java 16
List<String> strings = Stream.of("foo", "bar", "baz").collect(toList()); // Java 8

Maar gebruik bij voorkeur gewoon de Streamzonder deze te verzamelen in een List.

Als u specifiek een java.util.ArrayList*

nodig heeft

Als u beideeen ArrayListvooraf wilt invullen endaarna wilt toevoegen, gebruik dan

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

of in Java 8 of eerder:

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

of met behulp van Stream:

import static java.util.stream.Collectors.toCollection;
List<String> strings = Stream.of("foo", "bar")
                             .collect(toCollection(ArrayList::new));
strings.add("baz");

Maar nogmaals, het is beter om de Streamgewoon rechtstreeks te gebruiken in plaats van deze te verzamelen in een List.

*U hebt waarschijnlijk niet specifiek een ArrayListnodig. Om JEP 269te citeren:

Er is een klein aantalgebruiksscenario’s voor het initialiseren van een veranderlijke verzamelingsinstantie met een vooraf gedefinieerde set waarden. Het heeft meestal de voorkeur om die vooraf gedefinieerde waarden in een onveranderlijke verzameling te hebben en vervolgens de veranderlijke verzameling te initialiseren via een kopieerconstructor.

(nadruk van mij)

Programmeer naar interfaces, niet naar implementaties

Je zei dat je de lijst als een ArrayListin je code hebt gedeclareerd, maar je moet dat alleen doen als je een lid van ArrayListgebruikt dat niet in List.

Wat u waarschijnlijk niet doet.

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

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

Als u bijvoorbeeld een ArrayListdoorgeeft aan een 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
}

Een ander voorbeeld is het altijd declareren van een variabele een InputStream, ook al is het meestal een FileInputStreamof een BufferedInputStream, omdat u of iemand anders zal een ander soort InputStreamwillen gebruiken.


Antwoord 4, autoriteit 5%

Als je een eenvoudige lijst met maat 1 nodig hebt:

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

Als je een lijst met meerdere objecten nodig hebt:

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

Antwoord 5, autoriteit 3%

Met Guavakun je schrijven:

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

In Guava zijn er ook andere nuttige statische constructors. U kunt hiererover lezen.


6, Autoriteit 2%

Collection Literals haalden het niet in Java 8, maar het is mogelijk om de Stream API te gebruiken om een ​​lijst in één 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 Listeen ArrayListis:

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

7

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

8

U kunt een fabrieksmethode maken:

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");

Maar het is niet veel beter dan je eerste refactoring.

Voor meer flexibiliteit kan het generiek zijn:

public static <T> ArrayList<T> createArrayList(T ... elements) {
  ArrayList<T> list = new ArrayList<T>();
  for (T element : elements) {
    list.add(element);
  }
  return list;
}

9

In Java 9 kunnen we eenvoudig een ArrayListin een enkele regel initialiseren:

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

of

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

Deze nieuwe benadering van Java 9 heeft veel voordelen ten opzichte van de vorige:

  1. Ruimte-efficiëntie
  2. Immutability
  3. draad veilig

Zie dit bericht voor meer informatie – & GT; Wat is het verschil tussen lijst.van en Arrays.aslist?


10

Over de meest compacte manier om dit te doen is:

Double array[] = { 1.0, 2.0, 3.0};
List<Double> list = Arrays.asList(array);

11

Gebruik de onderstaande code gewoon als volgt.

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

Antwoord 12

Met Eclipse Collectionskun je het volgende schrijven:

List<String> list = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");

Je kunt ook specifieker zijn over de typen en of ze veranderlijk of onveranderlijk zijn.

MutableList<String> mList = Lists.mutable.with("Buenos Aires", "Córdoba", "La Plata");
ImmutableList<String> iList = Lists.immutable.with("Buenos Aires", "Córdoba", "La Plata");

Je kunt hetzelfde ook doen met Sets en Tassen:

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");

Opmerking:ik ben toegewijd aan Eclipse Collections.


Antwoord 13

Hier is een andere manier:

List<String> values = Stream.of("One", "Two").collect(Collectors.toList());

Antwoord 14

(Zou een reactie moeten zijn, maar te lang, dus nieuwe reactie). Zoals anderen al hebben vermeld, heeft de methode Arrays.asListeen vaste grootte, maar dat is niet het enige probleem ermee. Het gaat ook niet goed om met erfenissen. Stel dat u bijvoorbeeld het volgende heeft:

class A{}
class B extends A{}
public List<A> getAList(){
    return Arrays.asList(new B());
}

Het bovenstaande resulteert in een compilerfout, omdat List<B>(wat wordt geretourneerd door Arrays.asList) geen subklasse is van List<A>, ook al kunt u objecten van het type B toevoegen aan een List<A>-object. Om dit te omzeilen, moet je iets doen als:

new ArrayList<A>(Arrays.<A>asList(b1, b2, b3))

Dit is waarschijnlijk de beste manier om dit te doen, in het bijzonder. als u een onbegrensde lijst nodig heeft of overerving moet gebruiken.


Antwoord 15

U kunt de onderstaande verklaringen gebruiken:

Codefragment:

String [] arr = {"Sharlock", "Homes", "Watson"};
List<String> names = Arrays.asList(arr);

Antwoord 16

Zoals Tom zei:

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

Maar aangezien je klaagde dat je een ArrayList wilde, zou je eerst moeten weten dat ArrayList een subklasse is van List en je zou gewoon deze regel kunnen toevoegen:

ArrayList<String> myPlaces = new ArrayList(places);

Hoewel je daardoor zou kunnen klagen over ‘prestaties’.

In dat geval is het voor mij niet logisch, waarom, aangezien uw lijst vooraf is gedefinieerd, deze niet als een array is gedefinieerd (aangezien de grootte bekend is op het moment van initialisatie). En als dat een optie voor je is:

String[] places = {"Buenos Aires", "Córdoba", "La Plata"};

Als de kleine prestatieverschillen je niet interesseren, kun je ook heel eenvoudig een array naar een ArrayList kopiëren:

ArrayList<String> myPlaces = new ArrayList(Arrays.asList(places));

Ok, maar in de toekomst heb je iets meer nodig dan alleen de plaatsnaam, je hebt ook een landcode nodig. Ervan uitgaande dat dit nog steeds een vooraf gedefinieerde lijst is die tijdens runtime nooit zal veranderen, is het passend om een enum-set te gebruiken, die opnieuw moet worden gecompileerd als de lijst in de toekomst moet worden gewijzigd.

enum Places {BUENOS_AIRES, CORDOBA, LA_PLATA}

zou worden:

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;
    }
}

Enum’s hebben een statische values-methode die een array retourneert met alle waarden van de enum in de volgorde waarin ze zijn gedeclareerd, bijvoorbeeld:

for (Places p:Places.values()) {
    System.out.printf("The place %s has code %d%n",
                  p.name, p.code);
}

In dat geval denk ik dat je je ArrayList niet nodig hebt.

P.S. Randyaa demonstreerdenog een leuke manier met behulp van de statische hulpprogramma-methode Collections.addAll.


Antwoord 17

Java 9 heeft de volgende methode om een onveranderlijkelijst te maken:

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

die indien nodig gemakkelijk kan worden aangepast om een veranderlijke lijst te maken:

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

Vergelijkbare methoden zijn beschikbaar voor Seten Map.


Antwoord 18

List<String> names = Arrays.asList("2","@2234","21","11");

Antwoord 19

Ja, met behulp van Arrays kunt u de arraylijst op één regel initialiseren,

List<String> strlist= Arrays.asList("aaa", "bbb", "ccc");

Antwoord 20

Je kunt StickyListgebruiken van Cactoos:

List<String> names = new StickyList<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

21

Probeer met deze codelijn:

Collections.singletonList(provider)

22

In Java kun je

niet doen

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

Zoals opgemerkt, zou u een initialisatie van dubbele brace moeten doen:

List<String> places = new ArrayList<String>() {{ add("x"); add("y"); }};

Maar dit kan je dwingen om een ​​annotatie toe te voegen @SuppressWarnings("serial")of genereer een seriële UUID die irritant is. Ook de meeste codorme-formatters zullen dat in meerdere verklaringen / regels uitpakken.

Alternatief kunt u

doen

List<String> places = Arrays.asList(new String[] {"x", "y" });

Maar dan wilt u misschien een @SuppressWarnings("unchecked").

Ook volgens Javadoc zou u dit moeten doen:

List<String> stooges = Arrays.asList("Larry", "Moe", "Curly");

Maar ik kan het niet krijgen om te compileren met JDK 1.6.


23

Collections.singletonList(messageBody)

Als u een lijst met één artikel nodig hebt!

Collections is van java.util pakket.


Antwoord 24

De beste manier om het te doen:

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);
    }
}

Maak gewoon een functie die zoveel elementen kan hebben als je wilt en roep deze aan om ze op één regel toe te voegen.


Antwoord 25

Hier is de code van 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");

Verklaring: Ik ben de ontwikkelaar van AbacusUtil.


Antwoord 26

Gebruik Arrays.asList("Buenos Aires", "Córdoba", "La Plata");is correct. Maar gesprekken naar Arrays.asList()met nulargumenten of slechts één argument kan worden vervangen door een oproep naar Collections.singletonList()of Collections.emptyList()die een geheugen opslaat.

Opmerking: de lijst geretourneerd door Collections.singletonList()is onveranderlijk, terwijl de lijst Arrays.asList()heeft aangetroffen, kunt u de methode SET () mogelijk maken. Dit kan de code in zeldzame gevallen breken.


27

voor mij arrays.aslist () is de beste en handige. Ik hou ervan altijd op die manier te initialiseren.
Als u een beginner bent in Java-collecties, dan zou ik willen dat u ArrayList-initialisatie initialiseert


28

Waarom geen eenvoudige nutsfunctie maken die dit doet?

static <A> ArrayList<A> ll(A... a) {
  ArrayList l = new ArrayList(a.length);
  for (A x : a) l.add(x);
  return l;
}

ll” staat voor “Literal List”.

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

29

Interesseerder geen one-liner met de andere overbelasting Stream::collect-methode wordt vermeld

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

Other episodes