web-dev-qa-db-fra.com

Plusieurs contrôles nuls dans Java 8

J'ai le code ci-dessous qui est un peu moche pour plusieurs vérifications nulles.

String s = null;

if (str1 != null) {
    s = str1;
} else if (str2 != null) {
    s = str2;
} else if (str3 != null) {
    s = str3;
} else {
    s = str4;
}

J'ai donc essayé d'utiliser Optional.ofNullable comme ci-dessous, mais c'est encore difficile à comprendre si quelqu'un lit mon code. quelle est la meilleure approche pour le faire dans Java 8.

String s = Optional.ofNullable(str1)
                   .orElse(Optional.ofNullable(str2)
                                   .orElse(Optional.ofNullable(str3)
                                                   .orElse(str4)));

Dans Java 9, nous pouvons utiliser Optional.ofNullableavec OR, Mais en Java8, y a-t-il une autre approche?

97
sparker

Vous pouvez le faire comme ceci:

String s = Stream.of(str1, str2, str3)
    .filter(Objects::nonNull)
    .findFirst()
    .orElse(str4);
170
Ravindra Ranwala

Que diriez-vous de l'opérateur conditionnel ternaire?

String s = 
    str1 != null ? str1 : 
    str2 != null ? str2 : 
    str3 != null ? str3 : str4
;
72
Eran

Vous pouvez également utiliser une boucle:

String[] strings = {str1, str2, str3, str4};
for(String str : strings) {
    s = str;
    if(s != null) break;
}
33
ernest_k

Les réponses actuelles sont agréables, mais vous devriez vraiment mettre cela dans une méthode utilitaire:

public static Optional<String> firstNonNull(String... strings) {
    return Arrays.stream(strings)
            .filter(Objects::nonNull)
            .findFirst();
}

Cette méthode a été dans ma classe Util pendant des années, rend le code beaucoup plus propre:

String s = firstNonNull(str1, str2, str3).orElse(str4);

Vous pouvez même le rendre générique:

@SafeVarargs
public static <T> Optional<T> firstNonNull(T... objects) {
    return Arrays.stream(objects)
            .filter(Objects::nonNull)
            .findFirst();
}

// Use
Student student = firstNonNull(student1, student2, student3).orElseGet(Student::new);
26
walen

J'utilise une fonction d'aide, quelque chose comme

T firstNonNull<T>(T v0, T... vs) {
  if(v0 != null)
    return v0;
  for(T x : vs) {
    if (x != null) 
      return x;
  }
  return null;
}

Ensuite, ce type de code peut être écrit comme

String s = firstNonNull(str1, str2, str3, str4);
13
Michael Anderson

Une solution qui peut être appliquée à autant d'éléments que vous le souhaitez peut être:

Stream.of(str1, str2, str3, str4)
      .filter(Object::nonNull)
      .findFirst()
      .orElseThrow(IllegalArgumentException::new)

Vous pourriez imaginer une solution comme ci-dessous, mais la première assure non nullity pour tous les éléments

Stream.of(str1, str2, str3).....orElse(str4)
4
azro

Vous pouvez également regrouper toutes les chaînes dans un tableau de chaînes, puis faire une boucle for pour vérifier et rompre la boucle une fois qu'elle est affectée. En supposant que s1, s2, s3, s4 sont toutes des chaînes.

String[] arrayOfStrings = {s1, s2, s3};


s = s4;

for (String value : arrayOfStrings) {
    if (value != null) { 
        s = value;
        break;
    }
}

Modifié pour remettre la condition par défaut à s4 si aucune n'est affectée.

3
danielctw

Basée sur une méthode et simple.

String getNonNull(String def, String ...strings) {
    for(int i=0; i<strings.length; i++)
        if(strings[i] != null)
             return s[i];
    return def;
}

Et utilisez-le comme:

String s = getNonNull(str4, str1, str2, str3);

C'est simple à faire avec des tableaux et c'est joli.

3
Madhusoodan P

Si vous utilisez Apache Commons Lang 3, il peut être écrit comme ceci:

String s = ObjectUtils.firstNonNull(str1, str2, str3, str4);

L'utilisation de ObjectUtils.firstNonNull(T...) a été tirée de cette réponse . Différentes approches ont également été présentées dans des documents connexes question .

0
lczapski