Java 8可选仅在optional.isPresent时添加返回结果

Val*_*ale 10 java optional java-8 null-check

我有一段代码,其中一个接口有一个Optional返回方法,一些类实现它返回一些东西,其他没有.

为了拥抱这个辉煌的"空杀手",这是我尝试过的:

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>)
}}
Run Code Online (Sandbox Code Playgroud)

我为这个例子多么愚蠢而道歉.
我如何检查我刚刚获得的回报并仅在存在时添加它,使用可选项?

PS是否有任何真正有用的可选,如果(X!= null)不能做?

Mak*_*oto 16

我知道你要去哪里 - 当一个抛射物(可能是一个更好的类名Bullet)经过时BallisticGelPuddy,它会变得卡住或者没有.如果它卡住,它会累积进来BallisticGelPuddy.

如果我们使用null检查代替,我们会重写代码:

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

很简单,对吧?如果它存在,我们想要添加它.

让我们重新添加可选样式:

for(Gun gun: guns) {
    gun.shoot().ifPresent(bullets::add);
}
Run Code Online (Sandbox Code Playgroud)

实际上,这两件事情完成了同样的事情,尽管这种Optional方法更为严谨.

在这种情况下,这两种方法之间确实没有区别,因为您总是要检查是否存在. Optional意味着在处理时防止错误,null并允许您表达更流畅的调用链,但请考虑Optional在此方案中使用的实用性.对于这种情况,这似乎并非完全必要.


Boh*_*ian 11

我想你想要:

gun.shoot().ifPresent(bullets::add);
Run Code Online (Sandbox Code Playgroud)

或者您也可以免除(编码)循环:

guns.stream()
  .map(Gun::shoot)
  .filter(Optional::isPresent)
  .map(Optional::get)
  .forEach(bullets::add);
Run Code Online (Sandbox Code Playgroud)

但它更丑陋.