Сумма элементов при дубликате ключа с помощью Stream

Помогите пожалуйста. Мне из стрима необходимо получить Map, в котором в качестве ключа будет находиться остаток от деления, а в качестве value будет сумма чисел для которых этот остаток получился. Делитель дан заранее. вот мой код:

   int a = 2; делитель
    List<Integer> list = Arrays.asList(1, 2, 3 ,4, 5);
    Map<Integer, Integer> map = new HashMap<>();
    map = list.stream()
            .collect(Collectors.groupingBy(x -> list.get(x) % a,Collectors.summingInt(list::get)));
   System.out.println(map);

но у меня появляется ошибка java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5.

Объясните почему она появляется и что мне надо подкорректировать. ТАкже подскажите каким образом я бы мог использовать метод getOrDefault


Ответы (1 шт):

Автор решения: Alex Krass

В Collectors.groupingBy передается функция. Её описание говорит, что она преобразует входящие элементы в ключи. Поскольку это не индексы, а сами элементы, попытка получить элемент по индексу 5 заканчивается неудачей. Был бы у вас Arrays.asList(20);, то получили бы ошибку Index 20 out of bounds for length 5. Думаю логика понятная.

Вторая функция Collectors.summingInt принимает по описанию функцию преобразования элемента в int. Поскольку у вас опять же это не индекс, то вам просто надо преобразовать элемент Integer к int.

Советую вам выполнить и понять следующий код:

public static void main(String[] args){
     int a = 2;
     List<Integer> list = Arrays.asList(1, 10, 3, 12, 5);
     Map<Integer, Integer> map = new HashMap<>();
     map = list.stream()
             .collect(Collectors.groupingBy(x -> { 
                 System.out.println("получен элемент для преобразования в ключ: " + x +"; ключ " + x % a + ";");
                 return x % a; 
             }, Collectors.summingInt(x -> {
                 System.out.println("получен элемент для последующего сложения: " + x);
                 return x.intValue(); 
             })));
     System.out.println(map);
}

Итог:

map = list.stream()
             .collect(Collectors.groupingBy(x -> x % a, Collectors.summingInt(Integer::intValue)));
→ Ссылка