Java Lambda从列表中获取元素

DeM*_*rco 1 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);
    return target;
}
Run Code Online (Sandbox Code Playgroud)

但是,我试图让它变得更好一些(即只是想学习lambdas)

public Bar foo(int id) {
    Bar target = repo.stream().filter(c -> c.getId() == id)
               .findFirst().orElse(null);
    if(target == null){  
        target = new Bar();
        target.setFooo("");
        target.setId(0);
    }
    return target;
}
Run Code Online (Sandbox Code Playgroud)

但上面的代码返回一个ArrayOutOfBounds异常,我不确定如何(因为它是一个列表)或为什么.

Tag*_*eev 6

如果要使用函数式编程技术,最好重构代码,以便能够使用构造函数,构造函数或工厂方法完全构造对象.塞特斯是坏朋友,因为他们暗示可变性和功能编程喜欢不可改变的东西.

所以添加新的Bar构造函数:

public Bar(String fooo, int id) {
    this.fooo = fooo;
    this.id = id;
}
Run Code Online (Sandbox Code Playgroud)

在此之后您可能会意识到所有Bar对象都可以在没有setter的情况下使用.如果是这样,你可以简单地删除setter并将Bar字段设为final,这样Bar就会变成不可变的.即使你无法摆脱其他地方的setter,拥有新的构造函数,你的foo方法也可以用更清晰的方式重写:

public Bar foo(int id) {
    return repo.stream()
               .filter(c -> c.getId() == id)
               .findFirst()
               .orElseGet(() -> new Bar("", 0));
}
Run Code Online (Sandbox Code Playgroud)