使用并行流执行基于条件的加法

时间:2019-02-19 17:18:39

标签: java java-stream

我有一个第一种方法,其任务是根据条件as基本计算属性列表中条目的总和。我正在尝试使用并行流来实现这一点(可以说列表很大)。尽管我在这里使用原子双精度来处理竞争条件,但是我不确定这是否是最好的方法,因为Java8内置了许多功能。

代码:

public double getSum(List<SomeObject> list, boolean flag1, boolean flag2){
    AtomicDouble sum = new AtomicDouble();
    list.parallelStream().forEach(item -> {
        if(flag1){
            sum.addAndGet(flag2 ? item.getFirstData() : item.getSecondData());
        } else {
            sum.addAndGet(flag2 ? item.getThirdData() :item.getFourthData());
        }
    });
    return sum.doubleValue();
}

对于第二种方法,我们该怎么做:

enter code herepublic double getSum(Set<String> keys, HashMap<String, SomeObject> map, boolean flag1, boolean flag2){
    AtomicDouble sum = new AtomicDouble();

    keys.parallelStream().forEach(key -> {
        SomeObject item = map.get(key);
        if(flag1){
            sum.addAndGet(flag2 ? item.getFirstData() : item.getSecondData());
        } else {
            sum.addAndGet(flag2 ? item.getThirdData() :item.getFourthData());
        }
    });
    return sum.doubleValue();
}

2 个答案:

答案 0 :(得分:0)

根据注释中的建议并提供第二版代码,您可以使用以下约定。根据来自ToDoubleFunctionflag1的条件逻辑,创建一个flag2,如下所示:

boolean flag1, flag2; // provided as in your input
// create a ToDoubleFunction for conversion based on the above
ToDoubleFunction<SomeObject> chooseValue = new ToDoubleFunction<>() {
    @Override
    public double applyAsDouble(SomeObject value) {
        return flag1 ?
                flag2 ? value.getFirstData() : value.getSecondData() :
                flag2 ? value.getThirdData() : value.getFourthData();
    }
};

表示为:

ToDoubleFunction<SomeObject> chooseValue = value -> flag1 ?
        flag2 ? value.getFirstData() : value.getSecondData() :
        flag2 ? value.getThirdData() : value.getFourthData();

此后,在现有代码中使用相同的功能,您可以将其更新为:

public double getSum(List<SomeObject> list) {
    return list.parallelStream()
            .mapToDouble(chooseValue)
            .sum();
}

,并在您的更新版本中为

public double getSum(Set<String> keys, Map<String, SomeObject> map) {
    return keys.stream()
            .filter(map::containsKey)
            .map(map::get)
            .mapToDouble(chooseValue)
            .sum();
}

答案 1 :(得分:0)

将标志传递给方法一次,并且它们的值在其执行期间不会更改,因此无需为每个项目评估它们。此外,使用AtomicDouble似乎是多余的。您只应将该项目映射到double并让流对其进行求和:

public double getSum(List<SomeObject> list, boolean flag1, boolean flag2){
    ToDoubleFunction<SomeObject> mapper;
    if (flag1) {
        if (flag2) {
            mapper = SomeObject::getFirstData;
        } else {
            mapper = SomeObject::getSecondData;
        }
    } else {
        if (flag2) {
            mapper = SomeObject::getThirdData;
        } else {
            mapper = SomeObject::getFourthData;
        }
    }
    return list.parallelStream().mapToDouble(mapper).sum();
}