Java 8 - Разница между уменьшением (0, Integer::sum) и уменьшением (0, (a, b) -> a+b)
Я новичок в Java 8
и нашел несколько способов сделать addition
, multiply
а также subtraction
, Я буду публиковать вопрос только для добавления.
Я написал код ниже и собираю вывод в Sum1 и Sum2. Оба метода reduce(0, Integer::sum)
а также .reduce(0, (a, b) -> a+b);
дает тот же результат. Каков наилучший метод для повышения производительности, если используются большие целочисленные значения и почему?
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
Integer sum1 = numbers.stream().reduce(0, (a, b) -> a+b);
System.out.println("SUM ="+sum1);
Integer product = numbers.stream().reduce(0, (a, b) -> a*b);
System.out.println("PRODUCT = "+product);
int sum2 = numbers.stream().reduce(0, Integer::sum);
System.out.println("SUM 2= "+sum2);
Optional<Integer> sum3 = numbers.stream().reduce((a, b) -> (a + b));
System.out.println("SUM3="+sum3);
// Updated as per @Hadi J comment
int sum4 = numbers.stream().mapToInt(Integer::intValue).sum();
System.out.println("Sum ="+sum4);
2 ответа
Какой метод лучше всего использовать с точки зрения производительности и при использовании больших целочисленных значений и почему?
Основная идея состоит в том, чтобы игнорировать автоматическую упаковку / распаковку при манипулировании примитивами и их объектными представлениями.
Добавление двух Integer
объекты намного сложнее, чем добавление двух int
примитивы. Вы можете найти более подробную информацию в этом посте.
Так что лучший случай - это примитивный массив int[]
и суммируем его элементы в аккумулятор типа int
. Таким образом, здесь нет бокса.
Худший (но не худший) случай - это суммирование объекта Integer
с примитивным int
. Это вызовет распаковку первого аргумента. Вот как это работает, когда ваш исходный массив или коллекция содержит объекты (например, Integer[], List и т. Д....), а аккумулятор является примитивным. Это вызовет распаковку каждого элемента вашей коллекции ровно один раз, в то время как аккумулятор останется прежним.
Наихудший случай - суммирование коллекции объектов в Integer
аккумулятор.
Обычная старая Java:
Подведение итогов
Integer[]
вInteger
Integer[] array = {0,1,2,3,4,5,6,7,8,9}; Integer sum = 0; // Each element of the array will be unboxed exactly once // sum will be unboxed 10 times // result of the sum will be boxed 10 times for(int i : array) sum += i;
Подведение итогов
Integer[]
вint
Integer[] array = {0,1,2,3,4,5,6,7,8,9}; int sum = 0; // Each element of the array will be unboxed exactly once // result of the sum will be boxed 10 times for(int i : array) sum += i;
Подведение итогов
int[]
вint
int[] array = {0,1,2,3,4,5,6,7,8,9}; int sum = 0; // No boxing/unboxing at all for(int i : array) sum += i;
Stream API
Уменьшение суммы
Stream<Integer>
Stream<Integer> stream = Stream.of(0,1,2,3,4,5,6,7,8,9); // Each element will be unboxed exactly once // The accumulator will be unboxed 10 times // The result of the sum operation will be boxed 10 times Integer sum = stream.reduce(0, Integer::sum);
Уменьшение суммы
Stream<Integer>
отображение на примитивint
Stream<Integer> stream = Stream.of(0,1,2,3,4,5,6,7,8,9); // Each element will be unboxed exactly once // Neither accumulator not result will be unboxed/boxed int sum = stream.mapToInt(Integer::intValue).reduce(0, Integer::sum);
Уменьшение суммы
IntStream
IntStream stream = IntStream.of(0,1,2,3,4,5,6,7,8,9); // No boxing/unboxing at all int sum = stream.reduce(0, Integer::sum); // same as int sum2 = stream.sum();
Кое-что интересное: в Intellij IDEA, когда вы проводите мышью над функцией sum(), появляется всплывающая подсказка, подобная этой:
Возвращает сумму элементов в этом потоке. Это частный случай редукции и эквивалентен:
Public abstract int sum()
//equal function to
return reduce(0, Integer::sum);