Geliştirilmiş döngü için boş kontrol


172

Java for for döngüsünde null değerine karşı korunmanın en iyi yolu nedir?

Bu çirkin gözüküyor:

if (someList != null) {
    for (Object object : someList) {
        // do whatever
    }
}

Veya

if (someList == null) {
    return; // Or throw ex
}
for (Object object : someList) {
    // do whatever
}

Başka bir yol olmayabilir. forYapının kendisine koymuş olmalılarsa , eğer boşsa, döngüyü çalıştırmayın?


2
Muhtemelen bir NPE atmaktan daha iyidir. nullboş bir koleksiyonla aynı değildir.
Tom Hawtin - çakmak hattı

6
@GregMattes Şubat sorusu Ekim sorusunun bir kopyası mı?
Val

1
Collections.nonNullElementsIn (...) 'i kullanmanız yeterlidir: stackoverflow.com/a/34913556/5637185
Jeffrey Dilley

Yanıtlar:


227

Bu listeyi nereden alacağınızı daha iyi doğrulamanız gerekir.

Boş bir liste ihtiyacınız olmadığından boş bir liste yeterlidir.

Bu listeyi başka bir yerden alıyorsanız ve uygun olup olmadığını bilmiyorsanız, bir yardımcı program yöntemi oluşturabilir ve bu şekilde kullanabilirsiniz:

for( Object o : safe( list ) ) {
   // do whatever 
 }

Ve tabii ki safeşöyle olurdu:

public static List safe( List other ) {
    return other == null ? Collections.EMPTY_LIST : other;
}

57
Collections.emptyList () işlevinin fazladan bir nesne (IIRC) ayırmaktan kaçınacağını unutmayın.
Jon Skeet

7
@Jon: Ben her zaman kendime sordum, o emptyList java.sun.com/j2se/1.5.0/docs/api/java/util/… ' nin kullanımı neydi? IIRC nedir?
OscarRyz

11
IIRC = "Doğru hatırlıyorsam". Ve evet, Collections.emptyList () öğesine yapılan tüm çağrılar için döndürülen tek bir örnek var.
ColinD

Bu ... aslında soruya cevap vermiyor. Neden cevap kabul ediliyor?
Christopher Wirt

1
@ChristopherWirt çünkü şu soruya cevap veriyor: D
Tarik

100

Boş olarak geçtiğinizde boş bir sıra döndüren bir yardımcı yöntem yazabilirsiniz:

public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
    return iterable == null ? Collections.<T>emptyList() : iterable;
}

Sonra kullan:

for (Object object : emptyIfNull(someList)) {
}

Aslında bunu yapacağımı sanmıyorum - genellikle ikinci formunuzu kullanırdım. Özellikle, "veya eski atma" önemlidir - eğer gerçekten boş olmamalıysa, kesinlikle bir istisna atmalısınız. Bir şeyin yanlış gittiğini biliyorsun , ama hasarın boyutunu bilmiyorsun. Erken iptal et.


3
Her yinelenebilir bir liste olmadığı için Yinelenebilir <T> liste parametresini Yinelenebilir <T> yinelenebilir olarak değiştirirdim.
Lombo

Bu yöntemi kullanırken dikkatli olun: Koleksiyonlar sınıfının kullanımı nedeniyle, bu yöntemin kullanımı değişmez listenizi içerir
Tanorix

@tanorix: Ne şekilde?
Jon Skeet

@JonSkeet, Collections sınıfının emptyList () öğesinin değişmez bir liste döndürdüğünü görebilirsiniz : docs.oracle.com/javase/8/docs/api/java/util/…, böylece kullanıcı listesinin değişmez olmasını istemiyorsa sorunlu
Tanorix

@tanorix: Ama bu sorunun noktası hakkındadır yineleme döndürülen değeri üzerinde. Bu onu değiştirmez. Yıllardan Bu nedenle dönüş tipi emptyIfNullolan Iterable<T>- Orada talihsiz removeüzerinde yöntem Iterator<T>Bu açık değil, ama bu daha işin değişken yönünü var (? Ve boş bir koleksiyon var, neden ondan bir şey kaldırmaya çalışıyor) ne' buraya itiraz ediyoruz.
Jon Skeet

29

Zaten 2017 ve şimdi Apache Commons Koleksiyonlarını kullanabilirsiniz4

Kullanım:

for(Object obj : ListUtils.emptyIfNull(list1)){
    // Do your stuff
}

Aynı null-güvenli kontrolü ile diğer Koleksiyon sınıflarına yapabilirsiniz CollectionUtils.emptyIfNull.


2
Çalışır ama gereksiz liste nesnesi oluşturur. Bir CollectionUtils.ifNotEmpty daha ayrıntılı, ancak daha verimli ve daha hızlı olabilir. Çok önemli olmayacak ...
Lawrence

2
2017 yılında List.emptyIfNull (list1)
Dima

3
@Lawrence, yöntem yeni liste nesneleri oluşturmaz, Collections.emptyList()dahili olarak kullanır , bu da her zaman aynı önceden konumlandırılmış boş değiştirilemez listeyi döndürür.
Yoory N.

Myobject.getCompanies (). GetAddresses () öğesini çağırırsanız ve her ikisi de bir Liste döndürürse ve her ikisi de boş olabilir mi?
powder366

9

Java 8 ile Optional:

for (Object object : Optional.ofNullable(someList).orElse(Collections.emptyList())) {
    // do whatever
}

1
Basit üçlü operatörden daha ayrıntılı someList != null ? someList : Collections.emptyList()ve aynı zamanda bir Optionalnesne örneği oluşturur ve hemen atar .
Yoory N.

2
bu canavar çizgileri basit bir if (someList == null) ifadesinden daha zarif. Tek bir satıra bir banka uygulaması yazalım ...
Andreas Panagiotidis

8

Kullanım ArrayUtils.nullToEmptygelen commons-langDiziler için kütüphanede

for( Object o : ArrayUtils.nullToEmpty(list) ) {
   // do whatever 
}

Bu işlevsellik commons-lang, çoğu Java projesinde bulunan kitaplıkta bulunur.

// ArrayUtils.nullToEmpty source code 
public static Object[] nullToEmpty(final Object[] array) {
    if (isEmpty(array)) {
        return EMPTY_OBJECT_ARRAY;
    }
    return array;
}

// ArrayUtils.isEmpty source code
public static boolean isEmpty(final Object[] array) {
    return array == null || array.length == 0;
}

Bu @OscarRyz tarafından verilen cevapla aynıdır, ancak KURU mantra uğruna, kayda değer olduğuna inanıyorum. Bkz commons-lang proje sayfasını. İşte nullToEmptyAPI belgeleri ve kaynağı

commons-langHenüz girilmediyse projenize dahil edilecek maven girişi .

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.4</version>
</dependency>

Ne yazık ki, türler commons-langiçin bu işlevi sağlamaz List. Bu durumda, daha önce belirtildiği gibi bir yardımcı yöntem kullanmanız gerekir.

public static <E> List<E> nullToEmpty(List<E> list)
{
    if(list == null || list.isEmpty())
    {
        return Collections.emptyList();
    }
    return list;
}

7

Bunu alıyorsanız Listuygulamak bir yöntem çağrısından sonra dönmek yok null, boş döndürür List.

Uygulamayı değiştiremiyorsanız, o zaman nullçek ile sıkışmış . Olmaması gerekiyorsa null, bir istisna atın.

Boş bir liste döndüren yardımcı yöntem için gitmeyeceğim, çünkü bazen yararlı olabilir, ancak muhtemelen bazı hataları gizlediğiniz her döngüde çağırmaya alırdınız.


4

Yukarıdaki cevabı değiştirdim, bu yüzden Object'den yayın yapmanıza gerek yok

public static <T> List<T> safeClient( List<T> other ) {
            return other == null ? Collections.EMPTY_LIST : other;
}

ve sonra Listeleme yapan

for (MyOwnObject ownObject : safeClient(someList)) {
    // do whatever
}

Açıklama: MyOwnObject: Eğer List<Integer>öyleyse MyOwnObject bu durumda Tamsayı olacaktır.


1

For döngüsünde null değerine karşı etkili bir şekilde korunmanın bir başka yolu da, koleksiyonunuzu Google Guava'larla sarmaktır, Optional<T>çünkü umarım , müşterinin koleksiyonun mevcut olup olmadığını kontrol etmesi bekleneceği için etkili bir şekilde boş bir koleksiyonun olasılığını netleştirir Optional.isPresent().


1

Kendi statik null güvenlik yöntemini yazmakla ilgilenmeyen herkes için şunları kullanabilirsiniz: commons-lang's org.apache.commons.lang.ObjectUtils.defaultIfNull(Object, Object). Örneğin:

    for (final String item : 
    (List<String>)ObjectUtils.defaultIfNull(items, Collections.emptyList())) { ... }

ObjectUtils.defaultIfNull JavaDoc


Benim için bu cevap en zarif
Truong Nguyen

0

CollectionUtils.isEmpty(Collection coll)Belirtilen koleksiyonun boş olup olmadığını Null güvenli olan yöntem kullanın .

bunun için import org.apache.commons.collections.CollectionUtils.

Maven bağımlılığı

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>

-4
for (Object object : someList) {

   // do whatever
}  throws the null pointer exception.
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.