2011-04-05 21 views

risposta

202

La differenza principale è che Collections.emptyList() restituisce un immutabile elenco, ad esempio un elenco a cui non è possibile aggiungere elementi.

Nei rari casi in cui l'utente fa desidera modificare l'elenco restituito, ciò non rappresenta un'opzione.

Direi che restituire una lista immutabile è perfettamente soddisfacente (e anche il modo preferito) purché il contratto (documentazione) non dichiari esplicitamente in modo diverso.


Inoltre, emptyList()might not create a new object with each call.

implementazioni di questo metodo non è necessario creare un oggetto List separato per ciascuna chiamata. È probabile che l'utilizzo di questo metodo abbia costi comparabili con l'utilizzo del campo con nome simile. (A differenza di questo metodo, il campo non fornisce la sicurezza di tipo.)

L'attuazione di emptyList appare come segue:

public static final <T> List<T> emptyList() { 
    return (List<T>) EMPTY_LIST; 
} 

Quindi, se il metodo (che restituisce una lista vuota) viene chiamato molto spesso , questo approccio potrebbe anche darti prestazioni leggermente migliori sia della CPU che della memoria.

+3

Quindi, 'Collections.emptyList()' può essere più adatto per, ad esempio, controllo degli errori e simili? – mre

+3

Sì, lo direi. I client API – aioobe

+1

non riceveranno 'NullPointerException' restituendo' Collections.emptyList() 'invece di' null'. – realPK

24

Collections.emptyList è immutabile, quindi c'è una differenza tra le due versioni, quindi è necessario considerare gli utenti del valore restituito.

Il reso new ArrayList<Foo> restituisce sempre una nuova istanza dell'oggetto in modo che abbia un leggerissimo costo aggiuntivo associato che potrebbe fornire un motivo per utilizzare Collections.emptyList. Mi piace usare emptyList solo perché è più leggibile.

4

vorrei andare con Collections.emptyList() se l'elenco restituito non viene modificato in alcun modo (come la lista è immutabile), altrimenti andrei con l'opzione 2.

Il vantaggio di Collections.emptyList() è che la stessa istanza statica viene restituito ogni volta e quindi non si verifica la creazione dell'istanza per ogni chiamata.

40

partire con Java 5.0 è possibile specificare il tipo di elemento nel contenitore:

Collections.<Foo>emptyList() 

Concordo con le altre risposte che per i casi in cui si desidera restituire un elenco vuoto che rimane vuota, si dovrebbe usare questo approccio.

+22

A partire da Java 7, è possibile dedurre dal compilatore il parametro di tipo del richiamo del metodo generico dal tipo di destinazione: 'Elenco list = Collections.emptyList()' –

2

Utilizzare Collections.emptyList() se si desidera assicurarsi che l'elenco restituito non venga mai modificato.Questo è ciò che viene restituito a chiamare emptyList():

/** 
* The empty list (immutable). 
*/ 
public static final List EMPTY_LIST = new EmptyList(); 
+3

niente di nuovo rispetto alle risposte precedenti, vero? – kleopatra

+0

Sono arrivato qui cercando di scoprire se chiamare 'Collections.emptyList()' aveva un costo di costruzione. Vedere i dettagli di implementazione (anche se probabilmente non è la stessa su tutte le JVM) conferma che non è così. @Atul, da cui JVM è questo? – wjl

1

Le date risposte sottolineano il fatto che emptyList() restituisce un immutabile List ma non danno alternative. I casi particolari di costruzione ArrayList(int initialCapacity)0 in modo che tornano new ArrayList<>(0) invece di new ArrayList<>() potrebbe anche essere una soluzione praticabile:

/** 
* Shared empty array instance used for empty instances. 
*/ 
private static final Object[] EMPTY_ELEMENTDATA = {}; 

[...]

/** 
* Constructs an empty list with the specified initial capacity. 
* 
* @param initialCapacity the initial capacity of the list 
* @throws IllegalArgumentException if the specified initial capacity 
*   is negative 
*/ 
public ArrayList(int initialCapacity) { 
    if (initialCapacity > 0) { 
     this.elementData = new Object[initialCapacity]; 
    } else if (initialCapacity == 0) { 
     this.elementData = EMPTY_ELEMENTDATA; 
    } else { 
     throw new IllegalArgumentException("Illegal Capacity: "+ 
              initialCapacity); 
    } 
} 

(provenienti da sorgenti Java 1.8.0_72)

+0

Non sono d'accordo con il tuo approccio. Si salva un po 'di memoria e CPU durante l'inizializzazione, ma se la lista restituita viene modificata, si perde quel tempo quando l'elenco rialloca una nuova matrice. Se un sacco di elementi vengono aggiunti alla lista nel tempo, questo potrebbe accumularsi in un maggiore collo di bottiglia delle prestazioni a causa di [molto più lento tasso di crescita] (http://grepcode.com/file/repository.grepcode.com/java /root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.ensureCapacity%28int%29). Preferisco di gran lunga aderire alla convenzione di una lista vuota non modificabile o di una lista utilizzabile e modificabile. –

+1

Come ho cercato di sottolineare con la mia formulazione (_might be viable_): tutto dipende dal tuo caso d'uso. In generale, io/io restituirò le collezioni mutabili o inconfutabili, non una mescolanza a seconda che siano vuote o meno. E per contrastare la "richiesta molto più lenta": [questo] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/ArrayList.java# ArrayList.ensureCapacityInternal% 28int% 29) è l'implementazione corrente. –

+0

Oh uomo, guardami citando le versioni principali di JDK 2 obsolete. Quindi java8 evita completamente il collo di bottiglia facendo un salto fino alla capacità predefinita da una dimensione iniziale di 0. Mi spiace di aver sbagliato. –

5

Stai attento però. Se restituisci Collections.emptyList() e poi prova a fare alcune modifiche con esso come add() o smth del genere, avrai un UnsupportedOperationException() perché Collections.emptyList() restituisce un oggetto immutabile.

Problemi correlati