Как обрабатывать обнуляемые списки с помощью Java 8? - PullRequest
0 голосов
/ 27 декабря 2018

Я звоню в сервис и пытаюсь обработать ответ.Ответ может иметь список чего-либо.Этот список может быть нулевым.

Более того, если список не нулевой или не пустой, его необходимо отфильтровать.В коде «запись» ссылка может быть нулевой, если фильтрация ничего не дает или список ответов пуст или нулевой.

В настоящее время я получаю NPE, когда пытаюсь использовать stream () в пустом списке ответов.Как я могу справиться с этой ситуацией?

@Getter
public class ServiceResponse {  
    List<ResponseEntry> entryList;
}

@Getter
public class ResponseEntry {
    String value;
}


ServiceResponse serviceResponse = service.getServiceResponse();
ResponseEntry entry = serviceResponse.getEntryList()
    .stream()
    .filter(e -> "expectedValue".equals(e.getValue()))
    .findFirst()
    .orElse(null);

if (entry == null) { ... }

Ответы [ 5 ]

0 голосов
/ 27 декабря 2018

Другим вариантом будет использование Optional монады :

Optional<ResponseEntry> entry = Optional.ofNullable(serviceResponse.getEntryList()).flatMap(list ->
    list.stream().filter(e -> "expectedValue".equals(e.getValue())).findFirst()
);

if (!entry.isPresent()) {
    …
}

Вы можете даже использовать orElseGet вместо этого оператора ifесли ваша цель состоит в том, чтобы создать (и вернуть) значение вместо выполнения побочного эффекта.

0 голосов
/ 27 декабря 2018

Вы можете просто использовать троичный оператор:

ServiceResponse serviceResponse = service.getServiceResponse();
List<ResponseEntry> list = serviceResponse.getEntryList();

ResponseEntry entry = (list == null ? Collections.emptyList() : list)
    .stream()
    .filter(e -> "expectedValue".equals(e.getValue()))
    .findFirst()
    .orElse(null);

if (entry == null) { ... }

Иногда традиционный ИМО лучше.

0 голосов
/ 27 декабря 2018

В Java 9 вы можете использовать новый метод Objects.requireNonNullElse(T,T):

Objects.requireNonNullElse(serviceResponse.getEntryList(),
                           Collections.emptyList())

Apache Commons Collections на самом деле имеет метод ListUtils.emptyIfNull(List<T>), который возвращаетпустой список, если список аргументов null.Это даже лучше, но Objects.requireNonNullElse ближе всего к этому в Java SE.

Если вы ограничены только Java 8, то я согласен с ответом Aomine о том, что попытка сделать что-то вроде прохождения Optional хуже, чем if утверждение.

0 голосов
/ 27 декабря 2018

Stream.ofNullable (Java-9)

Возвращает последовательный поток, содержащий отдельный элемент , если не ноль , в противном случае возвращает пустой поток .

Текущий код

ResponseEntry entry = serviceResponse.getEntryList() // List<ResponseEntry>
        .stream() // NPE here   // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter
        .findFirst() // Optional<ResponseEntry>
        .orElse(null); // or else null

Обновленный код

ResponseEntry entry = Stream.ofNullable(serviceResponse.getEntryList()) // Stream<List<ResponseEntry>>
        .flatMap(List::stream) // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter here
        .findFirst() // Optional<ResponseEntry>
        .orElse(null); // or else null

Optional.stream (Java-9)

возвращает последовательный Stream , содержащий только это значение , в противном случае возвращает пустой поток .

ResponseEntry entry = Optional.ofNullable(serviceResponse.getEntryList())
        .stream() // Stream<List<ResponseEntry>>
        .flatMap(List::stream) // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter here
        .findFirst() // Optional<ResponseEntry>
        .orElse(null); // or else null

Optional.isEmpty (Java-11)

Если значение отсутствует , возвращает true , в противном случае false

Optional<ResponseEntry> entry = Optional.ofNullable(serviceResponse.getEntryList()) // Optional<List<ResponseEntry>>
        .orElseGet(Collections::emptyList) // or else empty List
        .stream() // Stream<ResponseEntry>
        .filter(e -> "expectedValue".equals(e.getValue())) // filter
        .findFirst(); // Optional<ResponseEntry>

if (entry.isEmpty()) { // !entry.isPresent in java-8
   // Do your work here
}
0 голосов
/ 27 декабря 2018

если список не нулевой или не пустой, его необходимо отфильтровать.

Здесь необязательно опционально, так как он не предназначен для замены простых if проверок.

ResponseEntry entry = null;
List<ResponseEntry> responseEntries = serviceResponse.getEntryList();
if(responseEntries != null && !responseEntries.isEmpty()){
    entry = responseEntries.stream()
                .filter(e -> "expectedValue".equals(e.getValue()))
                .findFirst()
                .orElse(null);
}
  • гласит: «если responseEntries не равно нулю и responseEntries не пусто, тогда примените операцию фильтрации и найдите первый элемент или, иначе, ноль».Очень удобочитаемый.

С другой стороны, необязательный подход:

ResponseEntry entry = Optional.ofNullable(serviceResponse.getEntryList())
                              .orElseGet(() -> Collections.emptyList())
                              .stream()
                              .filter(e -> "expectedValue".equals(e.getValue()))
                              .findFirst();

if(!entry.isPresent()){ ... } // or entry.ifPresent(e -> ...) depending on the logic you're performing inside the block
  • создает ненужные объекты, которые не следует использовать и которые на самом деле не предназначены для использования по желанию.в качестве замены простых проверок «если».
...