我试图用Java Lambda Expresions替换现有循环。
我有一个简单的数据结构,如下所示:
class DbObject{
private Long objectId;
private Long basedOnObjectId; //<- this field can be null
public Long getObjectId() {
return objectId;
}
public void setObjectId(Long objectId) {
this.objectId = objectId;
}
public Long getBasedOnObjectId() {
return basedOnObjectId;
}
public void setBasedOnObjectId(Long basedOnObjectId) {
this.basedOnObjectId = basedOnObjectId;
}
}
然后我有一个DbObjects列表
我试图用指定的basedOnObjectId筛选每个DbObject:
(1) list.stream().filter(object -> obejct.getBasedOnObjectId()
.equals(basedOnObject.getObjectId()))
.collect(Collector.of(List))
当然,这段代码为我提供了NullPointer,因为某些od DbObject因为它们是根而没有BasedOnObjectId。
很自然的事情是替换字段“ Long basedOnObjectId;”通过可选,但是正如我在开始时提到的那样,现有的生产代码无法快速解决。
因此,我尝试进行一些更改,我评估以下句子:
Optional<Long> option = Optional.ofNullable(objectWithNullBasedOnId.getBasedOnObjectId());
并尝试使用.get()方法或.ifPresent(),但.get()还会引发空指针异常,并且ifPresent不专用于处理流。
我注意到了这样的事实,即当我将DbObject的值设置为null basedOnObjectId时,我不必检查value是否恰好为null,而只需跳过此执行步骤。
因此,我决定使用.orElse()方法并返回一些假值。在这种情况下,我返回0L值,因为该索引在DB中不存在:)
所以我的代码:
(2) List newList = list.stream().filter(object -> Optional.ofNullable(object.getBasedOnObjectId())
.orElse(0L)
.equals(basedOnObject.getObjectId()) )
.collect(Collectors.toList()) ;
在这种情况下,这种方法可以正常工作,但是我认为这是一种解决方法。在其他语言中,可以使用空值跳过执行,也可以使用诸如skip-skipWhen方法之类的方法。
我的问题是:是否有可能使用java 8中的专用方法(例如Optional)达到(2)表达式的目标并编写“ in stream style” :)
最佳答案
如果比较Optional<Long>
而不是Long
,则无需区分当前对象和不存在对象。
Optional<Long> root = Optional.of(basedOnObject.getObjectId());
list.stream()
.map(DbObject::getBasedOnObjectId)
.map(Optional::ofNullable)
.filter(root::equals)
.collect(Collectors.toList());
在这种情况下,它甚至更简单,因为您可以反转比较:
list.stream()
.filter(o -> basedOnObject.getObjectId().equals(o.getBasedOnObjectId()))
.collect(Collectors.toList());