Похоже, что вы сделали необработанную ссылку на метод для конструктора ArrayList
с ArrayList::new
.
Аргумент типа не был выведен с помощью:
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll)
The Перегрузка с 3 аргументами collect
ожидает 3 аргумента, первый из которых - Supplier<R>
.На данный момент нет никакой связи между аргументом типа collect
метода R
и T
, который здесь Integer
.Единственный способ сделать вывод об этом - использовать второй аргумент, BiConsumer<R, ? super T>
.Здесь у вас есть ArrayList::add
, что не дает компилятору возможности сделать вывод R
.
Вы должны указать, что R
в первом аргументе, Поставщик.Вы можете предоставить явные аргументы типа классу для создания на основе ссылки на метод.
.collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll)
Компилируется, и вывод такой, как ожидается:
2
4
16
Когда вы используете Collectors.toList()
, вы предоставляете только один аргумент.
public static <T> Collector<T,?,List<T>> toList()
Здесь есть только один аргумент типа T
, поэтому компиляторможет правильно сделать вывод, что T
равен Integer
, поэтому создается List<Integer>
, что позволяет скомпилировать код.Аргументы типа для Collector
возвращают привязку T
к List<T>
, что позволяет компилятору выполнять вывод типа.
Обратите внимание, что это необходимо только в первую очередь, поскольку нет целевого типа дляпомочь с выводом типа;вы продолжаете манипулирование потоком и просто вызываете System.out.println
в конце, что может занять Object
.
Если бы у вас был этот код:
List<Integer> modified = list.stream()
.filter(x -> x > 0)
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
Тогда вывод целевого типа будетпредоставили Integer
для аргумента типа ArrayList::new
.Это также компилируется.