Java Lambda从列表中获取元素
我有以下代码,它使用良好的旧java工作:Java Lambda从列表中获取元素,java,lambda,java-8,java-stream,Java,Lambda,Java 8,Java Stream,我有以下代码,它使用良好的旧java工作: List<Bar> repo = ArrayList<>(); public Bar foo(int id) { for(Bar c: repo){ if(c.getId() == id) return c; } Bar target = new Bar(); target.setFooo(""); target.setId(0); retu
List<Bar> repo = ArrayList<>();
public Bar foo(int id) {
for(Bar c: repo){
if(c.getId() == id)
return c;
}
Bar target = new Bar();
target.setFooo("");
target.setId(0);
return target;
}
但是上面的代码返回了一个
ArrayOutOfBounds
异常,我不确定如何返回(因为它是一个列表)或者为什么返回 如果您想使用函数式编程技术,最好重构代码,以便能够完全使用构造函数、生成器或工厂方法构造对象。setter是坏朋友,因为它们意味着可变性,而函数式编程就像是不可变的东西
因此,添加新的Bar
构造函数:
public Bar(String fooo, int id) {
this.fooo = fooo;
this.id = id;
}
在此之后,您可能会意识到,所有Bar
对象都可以在没有设置器的情况下使用。如果是这样,您只需删除setter并将Bar
字段设置为final,这样Bar
将变得不可变。即使您无法在其他地方摆脱setter,使用新的构造函数,您的foo
方法也可以以更干净的方式重写:
public Bar foo(int id) {
return repo.stream()
.filter(c -> c.getId() == id)
.findFirst()
.orElseGet(() -> new Bar("", 0));
}
如果您想使用函数式编程技术,最好重构代码,以便能够完全使用构造函数、生成器或工厂方法构造对象。setter是坏朋友,因为它们意味着可变性,而函数式编程就像是不可变的东西 因此,添加新的
Bar
构造函数:
public Bar(String fooo, int id) {
this.fooo = fooo;
this.id = id;
}
在此之后,您可能会意识到,所有Bar
对象都可以在没有设置器的情况下使用。如果是这样,您只需删除setter并将Bar
字段设置为final,这样Bar
将变得不可变。即使您无法在其他地方摆脱setter,使用新的构造函数,您的foo
方法也可以以更干净的方式重写:
public Bar foo(int id) {
return repo.stream()
.filter(c -> c.getId() == id)
.findFirst()
.orElseGet(() -> new Bar("", 0));
}
您的解决方案与我的建议非常接近:
public Bar foo(int id) {
return repo.stream()
// find by id
.filter(c -> c.getId() == id)
// choose any
.findAny()
.orElseGet(() -> {
target = new Bar();
target.setFooo("");
target.setId(0);
return target;
});
}
不要创建更复杂的构造函数。它们甚至经常被称为反模式。坚持你的二传手
如果要优化,请让设置器返回更新的对象。这种方法将允许在未来增加任意数量的二传手。看起来是这样的:
public Bar setFooo(String fooo) {
this.fooo = fooo;
return this; // return modified instance
}
// do the same for setId()
代码后面一点:
.orElseGet(() -> new Bar()
.setFooo("")
.setId(0)
// add any number of future setters here
);
您的解决方案与我的建议非常接近:
public Bar foo(int id) {
return repo.stream()
// find by id
.filter(c -> c.getId() == id)
// choose any
.findAny()
.orElseGet(() -> {
target = new Bar();
target.setFooo("");
target.setId(0);
return target;
});
}
不要创建更复杂的构造函数。它们甚至经常被称为反模式。坚持你的二传手
如果要优化,请让设置器返回更新的对象。这种方法将允许在未来增加任意数量的二传手。看起来是这样的:
public Bar setFooo(String fooo) {
this.fooo = fooo;
return this; // return modified instance
}
// do the same for setId()
代码后面一点:
.orElseGet(() -> new Bar()
.setFooo("")
.setId(0)
// add any number of future setters here
);
据我所知,你的两个版本是相同的。我们需要知道更多的细节来说明导致异常的原因。上面的代码适合我。您可能在其他地方出错。最好删除
.orElse(null)
,更改为可选目标,然后使用if(bar.isPresent())返回bar.get()
,否则构造一个条newTarget
——更好的是,使用.orElseGet(()->{Bar newTarget=newbar();newTarget.setFooo(“”);newTarget.setId(0);return newTarget;})
我觉得第一个版本更好:)据我所知,您的两个版本是等效的。我们需要知道更多的细节来说明导致异常的原因。上面的代码适合我。您可能在其他地方出错。最好删除.orElse(null)
,更改为可选目标,然后使用if(bar.isPresent())返回bar.get()
,否则构造一个条newTarget
——更好的是,使用.orElseGet(()->{Bar newTarget=newbar();newTarget.setFooo(“”);newTarget.setId(0);return newTarget;})
我觉得第一个版本更好:)