仅当在Java8中使用lambda时不为null时才过滤值

vai*_*092 146 java null lambda nullpointerexception java-8

我有一个对象列表说car.我想基于使用Java 8的一些参数来过滤此列表.但是如果参数是null,它会抛出NullPointerException.如何过滤掉空值?

目前的代码如下

requiredCars = cars.stream().filter(c -> c.getName().startsWith("M"));
Run Code Online (Sandbox Code Playgroud)

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

xba*_*esx 296

在这个特定的例子中,我认为@Tagir是100%正确的,将它放入一个过滤器并进行两次检查.我不会使用Optional.ofNullable可选的东西真的是返回类型不做逻辑......但真的既不在这里也不在那里.

我想指出java.util.Objects在广泛的情况下有一个很好的方法,所以你可以这样做:

cars.stream()
    .filter(Objects::nonNull)
Run Code Online (Sandbox Code Playgroud)

这将清除你的空对象.对于不熟悉的人来说,这是以下方面的简写:

cars.stream()
    .filter(car -> Objects.nonNull(car))
Run Code Online (Sandbox Code Playgroud)

要部分回答手头的问题,请返回以下列内容开头的车名列表"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());
Run Code Online (Sandbox Code Playgroud)

一旦习惯了速记lambda,你也可以这样做:

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());
Run Code Online (Sandbox Code Playgroud)

不幸的是,一旦你.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());
Run Code Online (Sandbox Code Playgroud)

  • @kiedysktos这是一个很好的观点,调用`.startWith`也可能导致空指针.我试图提出的一点是,Java提供了一种专门用于从流中过滤掉空对象的方法. (3认同)

Tun*_*aki 49

您只需要过滤具有null名称的汽车:

requiredCars = cars.stream()
                   .filter(c -> c.getName() != null)
                   .filter(c -> c.getName().startsWith("M"));
Run Code Online (Sandbox Code Playgroud)

  • 真的很遗憾,这个答案并没有被高度评价,因为它似乎是实际回答这个问题的唯一答案. (3认同)
  • @MarkBooth 问题“如何过滤掉空值?” xbakesx 似乎回答得很好。 (2认同)

Joh*_*nny 38

建议的答案很棒.只是想提出一个改进使用处理空单的情况下Optional.ofNullable,用Java 8新特性:

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

那么,完整的答案将是:

 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
Run Code Online (Sandbox Code Playgroud)

  • 不好用的可选.null永远不应该首先用作空集合的同义词. (4认同)
  • @VGR当然,但这不是实践中发生的事情.有时(大多数情况下)您需要使用许多人工作的代码.有时您从外部接口接收数据.对于所有这些情况,Optional是一个很好的用途. (3认同)
  • 请注意,空车不是问题。在这种情况下,它的名称属性会导致问题。所以`Objects::nonNull` 不能解决问题,因为非空汽车可以有 name==null (3认同)

Tag*_*eev 20

您可以在单个过滤步骤中执行此操作:

requiredCars = cars.stream().filter(c -> c.getName() != null && c.getName().startsWith("M"));
Run Code Online (Sandbox Code Playgroud)

如果你不想getName()多次打电话(例如,这是一个昂贵的电话),你可以这样做:

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

或者以更复杂的方式:

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


rsl*_*mos 5

利用以下力量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())
;
Run Code Online (Sandbox Code Playgroud)