提问人:vaibhavvc1092 提问时间:10/1/2015 最后编辑:Tagir Valeevvaibhavvc1092 更新时间:9/21/2022 访问量:428806
仅在 Java8 中使用 lambda 不为 null 时才过滤值
Filter values only if not null using lambda in Java8
问:
我有一个对象列表说.我想使用 Java 8 根据某些参数过滤此列表。但是如果参数是 ,则抛出 .如何过滤掉空值?car
null
NullPointerException
当前代码如下
requiredCars = cars.stream().filter(c -> c.getName().startsWith("M"));
这将抛出 if 返回 .NullPointerException
getName()
null
答:
89赞
Tunaki
10/1/2015
#1
您只需要过滤有名称的汽车:null
requiredCars = cars.stream()
.filter(c -> c.getName() != null)
.filter(c -> c.getName().startsWith("M"));
评论
5赞
Mark Booth
5/4/2017
很遗憾,这个答案没有得到更多的投票,因为它似乎是唯一真正回答这个问题的答案。
2赞
vegemite4me
6/1/2017
@MarkBooth xbakesx 似乎很好地回答了“如何过滤掉空值”这个问题。
0赞
vegemite4me
6/2/2017
@MarkBooth 看日期你是对的。我的错误。
0赞
Vaibhav_Sharma
3/27/2019
性能方面,过滤流两次好还是更好地使用谓词进行过滤?只是想知道。
32赞
Tagir Valeev
10/1/2015
#2
您可以在单个筛选器步骤中执行此操作:
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());
评论
0赞
Paul
3/6/2020
第二个示例中的内联扩展对我的用例很有价值
513赞
xbakesx
5/24/2016
#3
在这个特定示例中,我认为@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());
一旦你习惯了速记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());
不幸的是,一旦你返回,你只会返回名字列表,而不是汽车。所以不那么漂亮,但完全回答了这个问题:.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());
评论
1赞
kiedysktos
1/9/2017
请注意,空车不是问题所在。在这种情况下,是 name 属性导致了问题。所以不能在这里使用,在最后的建议中,我相信它应该是Objects::nonNull
cars.stream() .filter(car -> Objects.nonNull(car.getName()))
1赞
kiedysktos
1/9/2017
顺便说一句,我认为这将是您在这个问题背景下的建议的总结cars.stream() .filter(car -> Objects.nonNull(car.getName()) && car.getName().startsWith("M"))
4赞
xbakesx
1/10/2017
@kiedysktos 这是一个很好的观点,调用也可能导致空指针。我想说的是,Java 提供了一种专门用于从流中过滤掉空对象的方法。.startWith
0赞
kiedysktos
5/4/2017
@Mark Booth 是的,显然等同于 ,你的选择更短Objects.nonNull
!= null
1赞
user1803551
10/4/2018
您不是创建汽车名称 () 而不是汽车 () 列表吗?String
Car
67赞
Johnny
8/29/2016
#4
建议的答案很棒。只是想提出一个改进建议,以处理使用 Java 8 中的新功能处理列表的情况:null
Optional.ofNullable
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
评论
7赞
VGR
12/13/2016
Optional 使用不当。首先,null 不应用作空 Collection 的同义词。
7赞
Johnny
12/13/2016
@VGR 当然,但这不是实践中发生的事情。有时(大多数时候)你需要使用很多人都在处理的代码。有时您会从外部接口接收数据。对于所有这些情况,“可选”都是一个很好的用途。
3赞
kiedysktos
1/9/2017
请注意,空车不是问题所在。在这种情况下,是 name 属性导致了问题。所以不能解决问题,因为非空车可以有 name==nullObjects::nonNull
1赞
Johnny
9/7/2017
当然@kiedysktos,但这不是我想在答案中展示的。但是,我接受你说的话并编辑答案:)
4赞
riverfan
7/19/2019
#5
你可以用这个
List<Car> requiredCars = cars.stream()
.filter (t-> t!= null && StringUtils.startsWith(t.getName(),"M"))
.collect(Collectors.toList());
4赞
rslemos
2/1/2020
#6
利用以下力量: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())
;
评论
0赞
Florian F
8/22/2023
恕我直言,使用 Optional 的复杂性来替换简单的布尔表达式是不好的做法。
评论