Java 8使用filter选项在嵌套列表中执行求和操作

时间:2017-11-04 16:51:35

标签: java lambda java-8 java-stream

让我们假设我有以下结构:

public class Athlete {
    private String      name;
    private int         someIdentifier;
    private Double      height;
    private Double      weight;
    private List<Shoes> shoes;
    // getters
    // setters
    public class Shoes {
        private String  name;
        private boolean ball;
        private int     someNumber;
        private int     someOtherNumber;
        // getters
        // setters
    }
}

我在这里收集了第一次迭代的列表List<Athlete> athleteList

现在我创建一个新的Athlete对象,我想检查它们是否已存在于我的列表中,如果它们存在,我想要对某些字段执行添加。

我已经尝试了以下工作正常:

athleteList.stream()
                     .filter(at -> filterAthlete(at, newAthlete))
                     .map(at -> mergeAthletes(at, newAthlete))
                     .collect(Collectors.toList());

private boolean filterAthlete(Athlete firstAthlete, Athlete secondAthlete) {
        if (firstAthlete.getName().equals(secondAthlete.getName())
                && firstAthlete.getSomeIdentifier() ==   secondAthlete.getSomeIdentifier()) {
            return true;
        } else {
            return false;
        }
    }

private Athlete mergeAthletes(Athlete firstAthlete, Athlete secondAthlete) {

        for (Shoes firstShoe : firstAthlete.getShoes()) {
            for (Shoes secondShoe : secondAthlete.getShoes()) {
                if (firstShoe.getBrand().equals(secondShoe.getBrand()) && firstShoe.getColor().equals(secondShoe.getColor())) {
                    firstShoe.setSomeNumber(firstShoe.getSomeNumber() + secondShoe.getSomeNumber());
                    firstShoe.setSomeOtherNumber(firstShoe.getSomeOtherNumber() + secondShoe.getSomeOtherNumber());
                }
            }
        }

        return firstAthlete;
    }

但是我想在mergeAthletes(...)方法中找到一种使用stream()的方法。

我想做类似的事情:

BiConsumer<Shoes, Shoes> reducer = (shoe1, shoe2) -> {
            shoe1.setSomeNumber(shoe1.getSomeNumber() + shoe2.getSomeNumber());
            shoe1.setSomeOtherNumber(shoe1.getSomeOtherNumber() + shoe2.getSomeOtherNumber());
        };

        Function<Shoes, List<Object>> compositeKey = shoes -> Arrays.<Object> asList(shoes.getBrand(),
                shoes.getColor());

在我的mergeAthletes方法中,使用 Function 代替我的if条件和 BiConsumer 代替每个循环的double中的添加,但是我没有想出怎么做。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:2)

firstAthlete.getShoes().forEach(shoe1 ->
    secondAthlete.getShoes().stream().filter(shoe2 -> 
        shoe1.getBrand().equals(shoe2.getBrand()) && shoe1.getColor().equals(shoe2.getColor()))
    ).forEach(shoe2 -> {
        shoe1.setSomeNumber(shoe1.getSomeNumber() + shoe2.getSomeNumber());
        shoe1.setSomeOtherNumber(shoe1.getSomeOtherNumber() + shoe2.getSomeOtherNumber());
    })

如果您的鞋子是不可变的(没有set...方法),那么您使用的是reduce而不是第二个forEach,可能还有map而不是第一个,取决于您的要求。

(另外,firstAthlete.getName() == secondAthlete.getName()很可能是一个错误,你想比较鞋子时需要equals。)