インターフェイスにオプションのreturnメソッドがあり、それを実装して何かを返すクラスがあるクラスとないクラスがあるコードがあります。
この見事な「null killer」を受け入れるために、私が試したのは次のとおりです。
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>)
}}
この例が愚かであることをお詫びします。
オプションを使用して、取得した返品を確認し、存在する場合にのみ追加するにはどうすればよいですか?
追伸Optionalには、if(X!= null)で実行できない実際の有用性はありますか?
私はこれであなたがどこへ向かっているのか分かります-発射物(Bullet
よりも良いクラス名かもしれません)がBallisticGelPuddy
を通過するとき、スタックするかしないかのどちらかです。スタックした場合、BallisticGelPuddy
に蓄積されます。
代わりに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
のアプローチはより簡潔ですが、これら2つのことで実質的に同じことを実現できます。
このシナリオでは、常に存在をチェックするため、2つのアプローチに違いはありません。 Optional
はnull
を処理するときの間違いを防ぐためのもので、 より流動的な呼び出しチェーンを表現する を可能にしますが、Optional
の使用の実用性を考慮してくださいこのシナリオでは。この場合、それは完全に必要とは思われません。
私はあなたが望むと思います:
gun.shoot().ifPresent(bullets::add);
または、(コード化された)ループも省略できます。
guns.stream()
.map(Gun::shoot)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(bullets::add);
しかし、それは醜いです。
ストリームAPIを使用すると、次のことができます。
List<Bullet> bullets = Arrays.stream(guns)
.map(Gun::shoot)
.flatMap(this::streamopt) // make Stream from Optional!
.collect(Collectors.toList());
残念ながら、Java 8には、OptionalをStreamに変換するメソッドがないため、自分で記述する必要があります。 sing Java 8's Stream :: flatMap のオプション
私がこれと同じような問題につまずいた人のために、今後の参考のためにこれを投稿したいと思います。存在する場合は、返されたばかりのメソッドにアクセスする必要があります。
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);});
}}