Насколько я могу судить, способ суммирования List<Double>
с использованием потоков Java 8:
List<Double> vals = . . . ;
double sum = vals.stream().mapToDouble(Double::doubleValue).sum();
Мне кажется, что mapToDouble(Double::doubleValue)
кажется крутым - это просто церемониальная церемония, которую лямбды и ручьи должны были обойтись без.
Лучшие практики говорят нам, что мы предпочитаем экземпляры List
для массивов, и все же для такого рода суммирования массивы кажутся более чистыми:
double[] vals = . . . ;
double sum = Arrays.stream(vals).sum();
Конечно, это можно сделать:
List<Double> vals = . . . ;
double sum = vals.stream().reduce(0.0, (i,j) -> i+j);
Но это reduce(....)
намного длиннее sum()
.
Я понимаю, что это связано с тем, как потоки необходимо модифицировать вокруг Java-объектов, не являющихся объектами, но все-таки я что-то упустил? Есть ли способ сжать автобоксинг, чтобы сделать это короче? Или это только текущее состояние искусства?
Обновление - дайджест ответов
Ниже приведен дайджест ответов. В то время как у меня есть резюме здесь, я настоятельно призываю читателя полностью ознакомиться с ответами.
@dasblinkenlight объясняет, что какой-то unboxing всегда будет необходим из-за решений, принятых еще в истории Java, в частности, в том, как были реализованы дженерики и их связь с неэлементными примитивами. Он замечает, что теоретически возможно, чтобы компилятор смог выполнить unboxing и разрешить более короткий код, но это еще не реализовано.
@Holger показывает решение, которое очень близко к выразительности, о которой я спрашивал:
double sum = vals.stream().reduce(0.0, Double::sum);
Я не знал о новом статическом методе Double.sum()
. Добавленный с 1.8, кажется, предназначен для самой цели, которую я описывал. Я также нашел Double.min()
и Double.max()
. В будущем я обязательно буду использовать эту идиому для таких операций на List<Double>
и т.д.