Действительно ли mapToDouble () действительно необходимо для суммирования List <Double> с потоками Java 8?

Насколько я могу судить, способ суммировать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 объясняет, что всегда требуется какая-то распаковка из-за решений, принятых еще в истории Java, особенно в том, как были реализованы дженерики и их связь с необъектными примитивами. Он отмечает, что для компилятора теоретически возможно интуитивно распаковать и разрешить более короткий код, но это еще не было реализовано.

@Holger показывает решение, очень близкое к выразительности, о которой я спрашивал:

double sum = vals.stream().reduce(0.0, Double::sum);

Я не знал о новой статикеDouble.sum() метод. Добавленный с 1.8, кажется, предназначенный для той самой цели, которую я описывал. Я также нашелDouble.min() а такжеDouble.max(), В дальнейшем я обязательно буду использовать эту идиому для таких операций наList<Double> и тому подобное.

Ответы на вопрос(3)

Ваш ответ на вопрос