Java 8 optional add return result only if optional.isPresent
Solution 1
I see where you're going with this - when a projectile (may be a better class name than Bullet
) goes through BallisticGelPuddy
, it either becomes stuck or it doesn't. If it gets stuck, it accumulates in BallisticGelPuddy
.
Let's rewrite the code if we were using null
checks instead:
for(Gun gun: guns) {
final Bullet bullet = gun.shoot();
if(bullet != null) {
bullets.add(bullet);
}
}
Pretty straightforward, right? If it exists we want to add it in.
Let's add the optional style back in:
for(Gun gun: guns) {
gun.shoot().ifPresent(bullets::add);
}
Effectively these two things accomplish the same thing, although the Optional
approach is terser.
In this scenario, there's really no difference between the two approaches since you're always going to be checking for existence. Optional
is meant to guard against mistakes when handling null
and allows you to express a more fluid call chain, but consider the practicality of using Optional
in this scenario. It doesn't seem entirely necessary for this case.
Solution 2
I think you want:
gun.shoot().ifPresent(bullets::add);
Or you can dispense with the (coded) loop too:
guns.stream()
.map(Gun::shoot)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(bullets::add);
But it's uglier.
Solution 3
With the stream API, you can do:
List<Bullet> bullets = Arrays.stream(guns)
.map(Gun::shoot)
.flatMap(this::streamopt) // make Stream from Optional!
.collect(Collectors.toList());
Unfortunately, in Java 8, there is no method which converts Optionals to Stream, so you need to write it yourself. See Using Java 8's Optional with Stream::flatMap
Vale
Updated on June 16, 2020Comments
-
Vale about 4 years
I have a piece of code where an interface has an Optional return method and some of the classes that implement it to return something, other don't.
In an effort to embrace this brilliant "null killer", here is what I have tried:
public interface Gun { public Optional<Bullet> shoot(); } public class Pistol implements Gun{ @Override public Optional<Bullet> shoot(){ return Optional.of(this.magazine.remove(0)); }//never mind the check of magazine content } public class Bow implements Gun{ @Override public Optional<Bullet> shoot(){ quill--; return Optional.empty(); } } public class BallisticGelPuddy{ private Gun[] guns = new Gun[]{new Pistol(),new Bow()}; private List<Bullet> bullets = new ArrayList<>(); public void collectBullets(){ //here is the problem for(Gun gun : guns) gun.shoot.ifPresent(bullets.add( <the return I got with the method>) }}
I apologise for how silly this example is.
How can I check the return I just got and add it only if present, using optional?P.S. is there any real usefulness to Optional which is if(X != null) couldn't do?