Inizializzazione dell'elenco Java in una riga

1. Introduzione

In questo breve tutorial, esamineremo come inizializzare un elenco utilizzando le battute.

2. Crea da un array

Possiamo creare una lista da un array e grazie ai letterali di array possiamo inizializzarli in una riga:

List list = Arrays.asList(new String[]{"foo", "bar"});

Possiamo fidarci del meccanismo varargs per gestire la creazione dell'array. In questo modo, possiamo scrivere codice più conciso e leggibile:

@Test public void givenArraysAsList_thenInitialiseList() { List list = Arrays.asList("foo", "bar"); assertTrue(list.contains("foo")); }

L'istanza del risultato di questo codice implementa l' interfaccia List ma non è java.util.ArrayListLinkedList . Invece, è un elenco supportato dall'array originale che ha due implicazioni.

Anche se il nome della classe sembra essere ArrayList, ma nel pacchetto java.util.Arrays .

2.1. Taglia unica

L'istanza del risultato da Arrays.asList avrà una dimensione fissa:

@Test(expected = UnsupportedOperationException.class) public void givenArraysAsList_whenAdd_thenUnsupportedException() { List list = Arrays.asList("foo", "bar"); list.add("baz"); }

2.2. Riferimento condiviso

L'array originale e l'elenco condividono gli stessi riferimenti agli oggetti:

@Test public void givenArraysAsList_whenCreated_thenShareReference(){ String[] array = {"foo", "bar"}; List list = Arrays.asList(array); array[0] = "baz"; assertEquals("baz", list.get(0)); }

3. Crea da uno stream (Java 8)

Possiamo facilmente convertire uno stream in qualsiasi tipo di raccolta.

Pertanto con i metodi factory per Streams , possiamo creare e inizializzare elenchi in una riga:

@Test public void givenStream_thenInitializeList(){ List list = Stream.of("foo", "bar") .collect(Collectors.toList()); assertTrue(list.contains("foo")); }

Dovremmo segnare qui che Collectors.toList () non garantisce l'esatta implementazione dell'elenco restituito .

Non esiste un contratto generale sulla mutabilità, serializzabilità o thread-safety dell'istanza restituita. Pertanto il nostro codice non dovrebbe fare affidamento su nessuna di queste proprietà.

Alcune fonti evidenziano che Stream.of (…) .collect (…) potrebbe avere una memoria e un'impronta di prestazioni maggiori rispetto a Arrays.asList () ma in quasi tutti i casi è una tale microottimizzazione che c'è poca differenza.

4. Metodi di fabbrica (Java 9)

In JDK 9, sono stati introdotti diversi metodi di fabbrica convenienti per le raccolte:

List list = List.of("foo", "bar", "baz"); Set set = Set.of("foo", "bar", "baz");

Un dettaglio importante è che le istanze restituite sono immutabili . Oltre a ciò, i metodi di fabbrica hanno diversi vantaggi in termini di efficienza dello spazio e sicurezza del filo.

Questo argomento è approfondito in questo articolo.

5. Inizializzazione Double-Brace

In diversi punti, possiamo trovare un metodo chiamato 'inizializzazione doppia parentesi graffa' che assomiglia a:

@Test public void givenAnonymousInnerClass_thenInitialiseList() { List cities = new ArrayList() {{ add("New York"); add("Rio"); add("Tokyo"); }}; assertTrue(cities.contains("New York")); }

Il nome "inizializzazione doppia parentesi graffa" è piuttosto fuorviante. La sintassi può sembrare compatta ed elegante ma nasconde pericolosamente ciò che sta succedendo.

In realtà non esiste un elemento di sintassi "doppia parentesi graffa" in Java, si tratta di due blocchi formattati intenzionalmente in questo modo.

Con le parentesi graffe esterne, dichiariamo una classe interna anonima che sarà una sottoclasse di ArrayList . All'interno di queste parentesi graffe, possiamo dichiarare i dettagli della nostra sottoclasse.

Come al solito, possiamo usare i blocchi inizializzatori di istanza ed è da lì che proviene la coppia interna di parentesi graffe.

La brevità di questa sintassi è allettante, tuttavia è considerata un anti-pattern.

Per saperne di più sull'inizializzazione della doppia parentesi graffa, dai un'occhiata al nostro articolo qui.

6. Conclusione

Modern Java offre diverse opzioni per creare una raccolta in una riga. Il metodo che abbiamo scelto dipende quasi interamente dalle preferenze personali, piuttosto che dal ragionamento tecnico.

Un aspetto importante è che, sebbene sembri grazioso, l'anti-pattern dell'inizializzazione anonima della classe interna ( nota anche come "doppia parentesi graffa") ha molti effetti collaterali negativi .

Come sempre, il codice è disponibile su GitHub.