Несколько нулевых проверок в Java 8

У меня есть код ниже, который немного уродлив для нескольких нулевых проверок.

String s = null;

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

Поэтому я попытался использовать Optional.ofNullable как Optional.ofNullable ниже, но все еще трудно понять, если кто-то читает мой код. Каков наилучший подход для этого в Java 8.

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

В Java 9 мы можем использовать Optional.ofNullable с OR, но в Java8 есть какой-то другой подход?

Ответ 1

Вы можете сделать это так:

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

Ответ 2

Как насчет троичного условного оператора?

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

Ответ 3

Вы также можете использовать цикл:

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

Ответ 4

Текущие ответы хороши, но вы действительно должны поместить это в служебный метод:

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

Этот метод был в моем классе Util течение многих лет, делает код намного чище:

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

Вы даже можете сделать его общим:

@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);

Ответ 5

Я использую вспомогательную функцию, что-то вроде

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

Тогда этот код может быть записан как

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

Ответ 6

Решение, которое может быть применено к любому количеству элементов, может быть:

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

Вы можете представить решение, как показано ниже, но первое гарантирует non nullity для всех элементов.

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

Ответ 7

Вы также можете объединить все строки в массив String, а затем выполнить цикл for, чтобы проверить и выйти из цикла после его назначения. Предполагая, что все s1, s2, s3, s4 являются строками.

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


s = s4;

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

Отредактировано, чтобы добавить условие по умолчанию для s4, если ни один не назначен.

Ответ 8

Метод основан и прост.

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

И использовать его как:

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

Это просто сделать с массивами и выглядит красиво.