我有一个对象列表,比如汽车。我想使用Java 8根据某些参数筛选这个列表。但如果参数为空,则抛出NullPointerException。如何过滤空值?

当前代码如下

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

如果getName()返回null,则抛出NullPointerException。


当前回答

利用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())
;

其他回答

你只需要过滤那些有空名字的车:

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

提议的答案很棒。只是想建议一个改进,以处理空列表使用可选的情况。nullable, Java 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

利用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())
;

你可以在一个过滤步骤中做到这一点:

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

你可以用这个

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