Collections.emptyList () ve yeni örnek


241

Uygulamada, daha iyi gibi boş bir liste döndürmektir bu :

return Collections.emptyList();

Veya gibi bu :

return new ArrayList<Foo>();

Yoksa bu tamamen iade edilen listeyle ne yapacağınıza bağlı mı?

Yanıtlar:


300

Temel fark, değiştirilemez bir liste, yani öğe ekleyemeyeceğiniz bir liste Collections.emptyList()döndürmesidir . (Aynısı Java 9'da tanıtılanlar için de geçerlidir .)List.of()

Eğer Nadiren do döndü listesinde değişiklik yapmak istiyorum, Collections.emptyList()ve List.of()böylece vardır değil iyi bir seçenek.

Sözleşme (dokümantasyon) açıkça farklı bir şekilde belirtilmediği sürece değişmez bir listeyi döndürmenin mükemmel bir şekilde (ve hatta tercih edilen yol) olduğunu söyleyebilirim.


Ayrıca, emptyList() her çağrıda yeni bir nesne oluşturmayabilir.

Bu yöntemin uygulamalarının her çağrı için ayrı bir List nesnesi oluşturması gerekmez. Bu yöntemin kullanılması, benzer adlı alanı kullanmanın karşılaştırılabilir maliyetine sahip olabilir. (Bu yöntemin aksine, alan tip güvenliği sağlamaz.)

Görünümlerin uygulanması emptyListaşağıdaki gibidir:

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

Dolayısıyla, yönteminiz (boş bir liste döndürür) çok sık çağrılırsa, bu yaklaşım size hem CPU hem de bellek açısından biraz daha iyi performans verebilir.


4
Collections.emptyList()Diyelim ki hata kontrolü ve benzerleri için daha uygun olur mu?
mre

1
API istemcileri bunun yerine NullPointerExceptiongeri dönerek elde edemez . Collections.emptyList()null
realPK

@PK_J önemli bir noktaya değiniyor. Collections.emptyList()yinelenebilir ve bir uzunluk döndürür, bu nedenle istisna olmadan döngüler için kullanılabilir.
ndm13 17:17

kullanmaya ne dersin List.of()?

4
@AJW, evet. Ancak, örneğin new ArrayList<>()tasarım kararını da netleştirir; öğeler bu listeye eklenmeyecek.
aioobe

51

Java 5.0 ile başlayarak kaptaki öğenin türünü belirleyebilirsiniz:

Collections.<Foo>emptyList()

Boş kalan boş bir listeyi geri döndürmek istediğiniz durumlarda bu yaklaşımı kullanmanız gereken diğer yanıtlarla hemfikirim.


38
Java 7 ile başlayarak, derleyicinin genel yöntem çağrısının type parametresini hedef türden çıkarmasına izin verebilirsiniz:List<Foo> list = Collections.emptyList()
Paul Jackson

28

Collections.emptyList değişmezdir, bu nedenle iki sürüm arasında bir fark vardır, bu nedenle döndürülen değeri dikkate almanız gerekir.

Geri dönmek new ArrayList<Foo>, nesnenin her zaman yeni bir örneğini oluşturur, bu nedenle, size kullanım için bir neden verebilecek çok hafif bir ekstra maliyete sahiptir Collections.emptyList. emptyListDaha okunabilir olduğu için kullanmayı seviyorum .


14

Yine de dikkatli olun. Eğer geri dönüp Collections.emptyList()sonra onun gibi add()ya da böyle bir şeyle bazı değişiklikler yapmaya çalışırsanız , u bir değişmez nesne döndürür UnsupportedOperationException()çünkü olacaktır Collections.emptyList().


7

Birlikte gider Collections.emptyList()yoksa ben 2 seçeneği ile gider, iade listesi (liste değişmez olduğu gibi) herhangi bir şekilde değiştirilen değilse.

Avantajı, Collections.emptyList()her seferinde aynı statik örneğin döndürülmesidir ve bu nedenle her çağrı için örnek oluşturma olmaz.


3

Döndürülen listenin hiçbir zaman değiştirilmediğinden emin olmak istiyorsanız Collections.emptyList () kullanın. EmptyList () çağrıldığında döndürülen budur:

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

Buraya arama Collections.emptyList()inşaat maliyeti olup olmadığını öğrenmek için çalışırken geldi . Uygulama ayrıntılarını görmek (muhtemelen tüm JVM'lerde aynı olmasa da) bunu doğrulamaz. @Atul, bu hangi JVM'den?
wjl

2

Verilen cevaplar emptyList()değişmez olanı döndüren Listancak alternatif vermeyenleri vurgular . Yapıcı yerine bu şekilde geri dönen ArrayList(int initialCapacity)özel durumlar da uygun bir çözüm olabilir:0new ArrayList<>(0)new ArrayList<>()

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

(Java 1.8.0_72 kaynakları)


Yaklaşımınıza katılmıyorum. Başlatma işleminde biraz bellek ve CPU kaydedersiniz, ancak döndürdüğünüz liste değiştirilirse, listenin yeni bir diziyi yeniden tahsis ettiği zamanı kaybedersiniz. Zamanla listeye çok sayıda öğe eklenirse , çok daha yavaş büyüme oranı nedeniyle daha fazla performans darboğazına neden olabilir . Değiştirilemez bir boş liste veya kullanılabilir, değiştirilebilir bir liste kuralına bağlı kalmayı tercih ederim.
Patrick M

1
İfadelerimle strese girmeye çalıştığım için ( uygun olabilir ): hepsi kullanım durumunuza bağlıdır. Genellikle olur ya da kesilebilir geri ya da boş ya da değil Hava bağlı unmutable Koleksiyonları, bir karışımıdır. Ve "çok daha yavaş iddiayı" karşı: Bu akım uygulamasıdır.
René

Ah adamım, JDK 2'nin ana sürümlerini güncel değilken bana bak. Böylece java8, başlangıçtaki 0 ​​boyutundan varsayılan kapasiteye atlayarak darboğazdan tamamen kaçınır. Üzgünüm, çok yanlıştım.
Patrick M
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.