Java 8 可选仅当可选时才添加返回结果。isPresent

2022-09-04 05:42:51

我有一段代码,其中接口具有Athose return方法和一些实现它以返回某些内容的类,其他则没有。

为了拥抱这个聪明的“空杀手”,以下是我尝试过的:

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>)
}}

我为这个例子有多愚蠢而道歉。
如何检查我刚刚获得的退货,并仅在存在时才使用可选添加?

P.S. Optional 是否有任何真正的用处,即 if(X != null) 不能做到?


答案 1

我知道你要去哪里 - 当一个射弹(可能是一个比)更好的类名通过时,它要么卡住,要么不卡住。如果它卡住,它会积聚在 .BulletBallisticGelPuddyBallisticGelPuddy

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

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

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

让我们将可选样式添加回去:

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

实际上,这两件事完成了同样的事情,尽管方法更简洁。Optional

在这种情况下,这两种方法之间实际上没有区别,因为您总是要检查是否存在。 旨在防止在处理时出现错误,并允许您表达更流畅的调用链,但请考虑在此方案中使用的实用性。对于这种情况,这似乎并不完全必要OptionalnullOptional


答案 2

我想你想要:

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

或者您也可以省去(编码)循环:

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

但它更丑陋。