Java 8 is optional to add a return result only if optional.isPresent

I have a piece of code in which the interface has an optional return method and some of the classes that implement it to return something, while others do not.

In an attempt to embrace this brilliant β€œzero killer”, here is what I 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 apologize for the stupidity of this example. How can I check the return I just received and add it only if it is present using optional?

PS is there any real usefulness for the optional, which is if (X! = Null) could not do?

+5
source share
4 answers

I see that you are going with this - when a projectile (maybe a better class name than Bullet ) passes through BallisticGelPuddy , it either gets stuck or not. If it gets stuck, it accumulates in BallisticGelPuddy .

Rewrite the code if we used null instead:

 for(Gun gun: guns) { final Bullet bullet = gun.shoot(); if(bullet != null) { bullets.add(bullet); } } 

Pretty simple, right? If it exists, we want to add it.

Add an extra style back to:

 for(Gun gun: guns) { gun.shoot().ifPresent(bullets::add); } 

Effectively, these two things do the same thing, although the Optional approach is the term.

In this case, there is no difference between the two approaches, since you will always check for existence. Optional designed to protect against errors when handling null and allows you to express a more flexible chain of calls , but consider the practicality of using Optional in this scenario. This does not seem absolutely necessary for this case.

+5
source

I think you want:

 gun.shoot().ifPresent(bullets::add); 

Or you can get by with a coded loop:

 guns.stream() .map(Gun::shoot) .filter(Optional::isPresent) .map(Optional::get) .forEach(bullets::add); 

But it's uglier.

+6
source

Using the stream API, you can:

  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 that converts Optionals to Stream, so you need to write it yourself. See Using Java 8 Options with Stream :: flatMap

+3
source

I want to publish this for future reference, for anyone who stumbles in a problem like mine. If you need access to the methods of what you just returned, if present:

 public class Bullet{ private int weight = 5; public int getWeight(){ return weigth;} } 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<>(); private int totWeigth = 0; public void collectBullets(){ // IF YOU WANT TO ONLY ADD WHAT YOU HAVE FOUND IN A COMPATIBLE CLASS // thanks to makoto and bohemian for the answers for(Gun gun : guns) gun.shoot.ifPresent(bullets::add) //IF YOU WANT TO ACCESS THE RETURNED OBJECT AND ADD IT TOO for(Gun gun : guns) gun.shoot.ifPresent( arg -> {totWeight += arg.getWeigth(); bullets.add(arg);}); }} 
0
source

All Articles