Выполнить сложение на основе условий, используя параллельные потоки - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть первый метод, задача которого состоит в том, чтобы в основном вычислять суммы записей в списке атрибутов на основе условий как.Я пытаюсь добиться этого с помощью параллельных потоков (скажем, список огромен).Хотя здесь я использую атомарный double для обработки состояния гонки, но я не уверен, что это лучший способ сделать это, поскольку 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 голосов
/ 19 февраля 2019

Флаги передаются методу один раз, и их значения не меняются во время его выполнения, поэтому нет необходимости оценивать их для каждого элемента.Кроме того, использование 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();
}
0 голосов
/ 19 февраля 2019

Как предлагается в комментариях и с учетом второй версии кода, вы можете использовать следующее соглашение.Создайте ToDoubleFunction на основе условной логики из flag1 и 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...