[java] Java8에서 람다를 사용하여 null이 아닌 경우에만 값 필터링

라고하는 객체 목록이 있습니다 car. Java 8을 사용하여 일부 매개 변수를 기준 으로이 목록을 필터링하고 싶습니다.하지만 매개 변수가 null이면 throw NullPointerException됩니다. null 값을 필터링하는 방법은 무엇입니까?

현재 코드는 다음과 같습니다

requiredCars = cars.stream().filter(c -> c.getName().startsWith("M"));

이 발생 NullPointerException하는 경우 getName()반환 null.



답변

이 특정 예제에서 @Tagir는 100 % 정확하다고 생각합니다. 하나의 필터로 가져 와서 두 가지 검사를 수행하십시오. Optional.ofNullable선택 사항을 사용하지 않는 것은 실제로 반환 유형이 논리를 수행하지 않는 것입니다 … 그러나 실제로 여기도 거기도 없습니다.

java.util.Objects광범위한 경우에 좋은 방법이 있다는 것을 지적하고 싶기 때문에 다음과 같이 할 수 있습니다.

cars.stream()
    .filter(Objects::nonNull)

null 객체가 지워집니다. 익숙하지 않은 사람에게는 다음과 같은 속기입니다.

cars.stream()
    .filter(car -> Objects.nonNull(car))

다음으로 시작하는 자동차 이름 목록을 반환하기 위해 해당 질문에 부분적으로 대답하려면 다음을 수행하십시오 "M".

cars.stream()
    .filter(car -> Objects.nonNull(car))
    .map(car -> car.getName())
    .filter(carName -> Objects.nonNull(carName))
    .filter(carName -> carName.startsWith("M"))
    .collect(Collectors.toList());

속기 람다에 익숙해지면 다음과 같이 할 수도 있습니다.

cars.stream()
    .filter(Objects::nonNull)
    .map(Car::getName)        // Assume the class name for car is Car
    .filter(Objects::nonNull)
    .filter(carName -> carName.startsWith("M"))
    .collect(Collectors.toList());

불행히도 일단 당신 .map(Car::getName)은 자동차가 아닌 이름의 목록 만 반환합니다. 그래서 아름답지는 않지만 질문에 완전히 대답합니다.

cars.stream()
    .filter(car -> Objects.nonNull(car))
    .filter(car -> Objects.nonNull(car.getName()))
    .filter(car -> car.getName().startsWith("M"))
    .collect(Collectors.toList());


답변

null이름 이있는 자동차 만 필터링하면됩니다 .

requiredCars = cars.stream()
                   .filter(c -> c.getName() != null)
                   .filter(c -> c.getName().startsWith("M"));


답변

제안 된 답변은 훌륭합니다. 그냥 사용하여 널리스트의 경우를 처리하기 위해 개선을 제안하고자 Optional.ofNullable, 자바 8의 새로운 기능 :

 List<String> carsFiltered = Optional.ofNullable(cars)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

따라서 전체 답변은 다음과 같습니다.

 List<String> carsFiltered = Optional.ofNullable(cars)
                .orElseGet(Collections::emptyList)
                .stream()
                .filter(Objects::nonNull) //filtering car object that are null
                .map(Car::getName) //now it's a stream of Strings
                .filter(Objects::nonNull) //filtering null in Strings
                .filter(name -> name.startsWith("M"))
                .collect(Collectors.toList()); //back to List of Strings


답변

단일 필터 단계에서이 작업을 수행 할 수 있습니다.

requiredCars = cars.stream().filter(c -> c.getName() != null && c.getName().startsWith("M"));

getName()여러 번 전화하고 싶지 않은 경우 (예 : 비싼 통화) 다음과 같이하면됩니다.

requiredCars = cars.stream().filter(c -> {
    String name = c.getName();
    return name != null && name.startsWith("M");
});

또는 더 복잡한 방식으로 :

requiredCars = cars.stream().filter(c ->
    Optional.ofNullable(c.getName()).filter(name -> name.startsWith("M")).isPresent());


답변

의 힘을 활용 java.util.Optional#map():

List<Car> requiredCars = cars.stream()
  .filter (car ->
    Optional.ofNullable(car)
      .map(Car::getName)
      .map(name -> name.startsWith("M"))
      .orElse(false) // what to do if either car or getName() yields null? false will filter out the element
    )
  .collect(Collectors.toList())
;


답변

이것을 사용할 수 있습니다

List<Car> requiredCars = cars.stream()
    .filter (t->  t!= null && StringUtils.startsWith(t.getName(),"M"))
    .collect(Collectors.toList());


답변