Java 8 可选添加 return 结果仅当 optional.isPresent
Java 8 optional add return result only if optional.isPresent
我有一段代码,其中一个接口有一个可选的 return 方法和一些 类 将它实现为 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>)
}}
对于这个例子的愚蠢,我深表歉意。
如何检查我刚得到的 return 并仅在存在时添加它,使用可选的?
P.S。 Optional 是否真的有用,而 if(X != null) 做不到?
我想你想要:
gun.shoot().ifPresent(bullets::add);
或者您也可以省去(编码的)循环:
guns.stream()
.map(Gun::shoot)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(bullets::add);
但是比较丑
我明白你的意思了——当一个射弹(class 的名字可能比 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
方法更简洁,但实际上这两件事完成的是同一件事。
在这种情况下,这两种方法之间确实没有区别,因为您总是要检查是否存在。 Optional
是为了防止在处理 null
时出错,并允许您 express a more fluid call chain,但请考虑在这种情况下使用 Optional
的实用性。对于这种情况,似乎并不完全必要。
使用流 API,您可以:
List<Bullet> bullets = Arrays.stream(guns)
.map(Gun::shoot)
.flatMap(this::streamopt) // make Stream from Optional!
.collect(Collectors.toList());
遗憾的是,Java8中没有将Optionals转为Stream的方法,需要自己写。
参见 Using Java 8's Optional with Stream::flatMap
我想post这个以供将来参考,以供遇到与我类似的问题的任何人使用。您是否想要访问刚刚返回的方法(如果存在):
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);});
}}
我有一段代码,其中一个接口有一个可选的 return 方法和一些 类 将它实现为 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>)
}}
对于这个例子的愚蠢,我深表歉意。
如何检查我刚得到的 return 并仅在存在时添加它,使用可选的?
P.S。 Optional 是否真的有用,而 if(X != null) 做不到?
我想你想要:
gun.shoot().ifPresent(bullets::add);
或者您也可以省去(编码的)循环:
guns.stream()
.map(Gun::shoot)
.filter(Optional::isPresent)
.map(Optional::get)
.forEach(bullets::add);
但是比较丑
我明白你的意思了——当一个射弹(class 的名字可能比 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
方法更简洁,但实际上这两件事完成的是同一件事。
在这种情况下,这两种方法之间确实没有区别,因为您总是要检查是否存在。 Optional
是为了防止在处理 null
时出错,并允许您 express a more fluid call chain,但请考虑在这种情况下使用 Optional
的实用性。对于这种情况,似乎并不完全必要。
使用流 API,您可以:
List<Bullet> bullets = Arrays.stream(guns)
.map(Gun::shoot)
.flatMap(this::streamopt) // make Stream from Optional!
.collect(Collectors.toList());
遗憾的是,Java8中没有将Optionals转为Stream的方法,需要自己写。 参见 Using Java 8's Optional with Stream::flatMap
我想post这个以供将来参考,以供遇到与我类似的问题的任何人使用。您是否想要访问刚刚返回的方法(如果存在):
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);});
}}