Archivage nul dans une boucle for améliorée

172

Quelle est la meilleure façon de se prémunir contre null dans une boucle for en Java?

Cela semble moche:

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

Ou

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

Il n'y a peut-être pas d'autre moyen. Auraient-ils dû le mettre dans la forconstruction elle-même, s'il est nul, alors ne lancez pas la boucle?

fastcodejava
la source
2
Vous feriez probablement mieux de lancer un NPE. nulln'est pas la même chose qu'une collection vide.
Tom Hawtin - tackline
6
@GregMattes Comment la question de février est-elle un double de la question d'octobre?
Val
1
Il suffit d'utiliser Collections.nonNullElementsIn (...): stackoverflow.com/a/34913556/5637185
Jeffrey Dilley

Réponses:

228

Vous devriez mieux vérifier d'où vous obtenez cette liste.

Une liste vide est tout ce dont vous avez besoin, car une liste vide n'échouera pas.

Si vous obtenez cette liste ailleurs et que vous ne savez pas si c'est correct ou non, vous pouvez créer une méthode utilitaire et l'utiliser comme ceci:

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

Et bien sûr safeserait:

public static List safe( List other ) {
    return other == null ? Collections.EMPTY_LIST : other;
}
OscarRyz
la source
57
Notez que Collections.emptyList () évitera d'allouer un objet supplémentaire (IIRC).
Jon Skeet
7
@Jon: Je me suis toujours demandé à moi-même, quelle était l'utilité de ce emptyList java.sun.com/j2se/1.5.0/docs/api/java/util/ ... Qu'est-ce que l'IIRC?
OscarRyz
11
IIRC = "Si je me souviens bien". Et oui, il existe une instance de singleton qui est renvoyée pour tous les appels à Collections.emptyList ().
ColinD le
Cela ... ne répond pas vraiment à la question. Pourquoi est-ce une réponse acceptée?
Christopher Wirt
1
@ChristopherWirt parce qu'il répond à la question: D
Tarik
100

Vous pourriez potentiellement écrire une méthode d'assistance qui retournait une séquence vide si vous passiez null:

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

Puis utilisez:

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

Je ne pense pas que je le ferais réellement - j'utiliserais généralement votre deuxième formulaire. En particulier, le "or throw ex" est important - s'il ne doit vraiment pas être nul, vous devez absolument lancer une exception. Vous savez que quelque chose ne va pas, mais vous ne connaissez pas l'étendue des dégâts. Abandonnez tôt.

Jon Skeet
la source
3
Je changerais le paramètre de liste Iterable <T> en Iterable <T> iterable, car tous les itérables ne sont pas une liste.
Lombo
Soyez prudent en utilisant cette méthode: en raison de l'utilisation de la classe Collections, l'utilisation de cette méthode implique que votre liste soit immuable
Tanorix
@tanorix: De quelle manière?
Jon Skeet
@JonSkeet vous pouvez voir que emptyList () de la classe Collections renvoie une liste immuable: docs.oracle.com/javase/8/docs/api/java/util/… donc si l'utilisateur ne veut pas que sa liste soit immuable, il peut être problématique
Tanorix
@tanorix: Mais le but de cette question est d' itérer sur la valeur renvoyée. Cela ne le modifie pas. C'est pourquoi le type de retour emptyIfNullest Iterable<T>- il y a la removeméthode malheureuse Iterator<T>, mais c'est le seul aspect modifiable de celui-ci (et si vous avez une collection vide, pourquoi essayez-vous d'en supprimer quoi que ce soit?) Ce n'est pas clair ce que vous '' vous vous opposez ici.
Jon Skeet
29

Nous sommes déjà en 2017 et vous pouvez désormais utiliser Apache Commons Collections4

L'usage:

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

Vous pouvez effectuer la même vérification de sécurité nulle sur d'autres classes Collection avec CollectionUtils.emptyIfNull.

Fred Pym
la source
2
Fonctionnera bien que crée un objet de liste inutile. Un CollectionUtils.ifNotEmpty peut être plus détaillé mais plus efficace et plus rapide. Pas que cela importerait beaucoup ...
Lawrence
2
En 2017, je m'attendrais à List.emptyIfNull (list1)
Dima
3
@Lawrence, la méthode ne crée pas de nouveaux objets de liste, elle les utilise en Collections.emptyList()interne, qui à son tour renvoie toujours la même liste vide non modifiable préallouée.
Yoory N.
Que faire si vous appelez myobject.getCompanies (). GetAddresses () et que les deux renvoient une liste et que les deux peuvent être null?
poudre366
9

Avec Java 8 Optional:

for (Object object : Optional.ofNullable(someList).orElse(Collections.emptyList())) {
    // do whatever
}
holmis83
la source
1
Son plus verbeux qu'un simple opérateur ternaire aime someList != null ? someList : Collections.emptyList()et crée également et jette immédiatement une instance d' Optionalobjet.
Yoory N.27
2
comment ces lignes monstrueuses sont-elles plus élégantes qu'une simple instruction if (someList == null). Écrivons une demande bancaire en une ligne ...
Andreas Panagiotidis
8

Utilisation à ArrayUtils.nullToEmptypartir de la commons-langbibliothèque pour les tableaux

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

Cette fonctionnalité existe dans la commons-langbibliothèque, qui est incluse dans la plupart des projets Java.

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

C'est la même chose que la réponse donnée par @OscarRyz, mais pour le bien du mantra DRY , je pense que cela vaut la peine de le noter. Voir la page du projet commons-lang . Voici la documentation de l' nullToEmptyAPI et la source de

Entrée Maven à inclure commons-langdans votre projet si ce n'est déjà fait.

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

Malheureusement, commons-langne fournit pas cette fonctionnalité pour les Listtypes. Dans ce cas, vous devrez utiliser une méthode d'assistance comme mentionné précédemment.

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

Si vous obtenez cela à Listpartir d'un appel de méthode que vous implémentez, ne retournez pas null, retournez unList .

Si vous ne pouvez pas modifier l'implémentation, vous êtes coincé avec le nullchèque. Si ça ne devrait pas êtrenull , lancez une exception.

Je n'irais pas pour la méthode d'assistance qui renvoie une liste vide car elle peut être utile parfois, mais vous vous habitueriez à l'appeler dans chaque boucle que vous faites en cachant éventuellement des bogues.

Lombo
la source
4

J'ai modifié la réponse ci-dessus, vous n'avez donc pas besoin de lancer depuis Object

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

puis appelez simplement la liste par

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

Explication: MyOwnObject: If List<Integer>then MyOwnObject sera Integer dans ce cas.

Haris Iltifat
la source
1

Une autre façon de se prémunir efficacement contre un null dans une boucle for consiste à envelopper votre collection avec Google Guava Optional<T>car cela, on l'espère, rend la possibilité d'une collection effectivement vide claire puisque le client devrait vérifier si la collection est présente avec Optional.isPresent().

Nico de Wet
la source
1

Pour quiconque n'est pas intéressé par l'écriture de sa propre méthode de sécurité nulle statique, vous pouvez utiliser: commons-lang's org.apache.commons.lang.ObjectUtils.defaultIfNull(Object, Object). Par exemple:

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

ObjectUtils.defaultIfNull JavaDoc

Jacob Briscoe
la source
Pour moi, cette réponse est la plus élégante
Truong Nguyen
0

Utilisez, CollectionUtils.isEmpty(Collection coll)méthode qui est Null-safe vérifie si la collection spécifiée est vide.

pour cela import org.apache.commons.collections.CollectionUtils.

Dépendance Maven

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.0</version>
</dependency>
Swadeshi
la source
-4
for (Object object : someList) {

   // do whatever
}  throws the null pointer exception.
user6315386
la source