Reputation: 915
I trying to replace existing loop with java lambda expresions.
I have simple data structure that looks like follow:
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;
}
}
Then I have a List of DbObjects
And I trying to filter each DbObject with specified basedOnObjectId:
(1) list.stream().filter(object -> obejct.getBasedOnObjectId()
.equals(basedOnObject.getObjectId()))
.collect(Collector.of(List))
Of course this code gives me NullPointer because some od DbObject didn't have BasedOnObjectId because they are roots.
So natural thing is to replace field "Long basedOnObjectId;" by Optional but as I mentioned at start there are existing production code co it isn't fast fix.
So I trying to make some changes, I evaluate following sentence:
Optional<Long> option = Optional.ofNullable(objectWithNullBasedOnId.getBasedOnObjectId());
And Try with .get() method or .ifPresent() but .get() also throw null pointer exception and ifPresent is not dedicated to work with stream.
I noticed that and the fact that When I have DbObject with null basedOnObjectId I don't have to check if value is exactly null but only skip this step of execution.
So I decided to use .orElse() method and return some fake value. In this case i return 0L value because this index don't exist in DB :)
So my code :
(2) List newList = list.stream().filter(object -> Optional.ofNullable(object.getBasedOnObjectId())
.orElse(0L)
.equals(basedOnObject.getObjectId()) )
.collect(Collectors.toList()) ;
And this work correctly in this case, but I think this is some kind of workaround. In other languages are possible to skip execution with null value, or use some like skip-skipWhen methods.
My question is : if exist possibility to reach the goal of (2) expression using dedicated method (in example Optional) from java 8 and write "in stream style" :)
Upvotes: 0
Views: 2424
Reputation: 95346
You don't need to introduce Optional
here. You just need to be aware that null is in your domain, and deal accordingly. Like this:
list.stream().filter(o -> Objects.equals(o.getBasedOnObjectId(),
basedOnObject.getObjectId()))
.collect(toList());
or by filtering out the nulls explicitly (.filter(o -> o.getBasedOnObjectId() != null
) or by rolling a null check into your existing filter condition.
No reason to make this more complicated than it needs to be. Objects.equals()
is likely what you want, just use that.
Upvotes: 5
Reputation: 50044
If you compare Optional<Long>
instead of Long
, there is no need for a distinction between present and absent objects.
Optional<Long> root = Optional.of(basedOnObject.getObjectId());
list.stream()
.map(DbObject::getBasedOnObjectId)
.map(Optional::ofNullable)
.filter(root::equals)
.collect(Collectors.toList());
In this case, it is even simpler, because you can just reverse the comparison:
list.stream()
.filter(o -> basedOnObject.getObjectId().equals(o.getBasedOnObjectId()))
.collect(Collectors.toList());
Upvotes: 3
Reputation: 4532
You probably want to actually remove the null objects from the stream before passing them to subsequent operations. Try mapping the objects to the BasedOnObjectId form and then filtering the null values:
list.stream()
.map(object -> object.getBasedOnObjectId())
.filter(object -> object != null)
...
Upvotes: 3