Java 8, Stream API, Generics что я упустил?

161
11 июля 2018, 17:50
List list = new ArrayList();
Stream<Object> stream = list.stream();
// маппинг так для примера
List<String> collect = stream.map(obj -> obj.toString()) 
        .collect(toList());

Что я упустил в дженериках? Эта конструкция валидна, но убирая дженерик у стрима Stream stream = list.stream(); уже не валидна?

Или же так, зачем это кастование? (List<Object>) list

List<String> collect = ((List<Object>) list).stream.map(obj -> obj.toString()) 
            .collect(toList());
Answer 1

Ответ дан здесь, но так как это StackOverflow на русском, приведу перевод:

stream(), map(), collect() и все другие stream методы завязаны на дженериках. Если опустить их использование, то все сопутствующие дженерики в библиотеках также будут опущены и все структуры превратятся в обычные интерфейсы без указания типа. К примеру, если вы используете List<String>, то вызвав метод stream(), получите Stream<String>.

Однако если вы вызовите stream() у объекта с типом List без указания типа, то вернётся объект Stream.

Метод map() в этом же случае имеет следующее объявление:

<R> Stream<R> map(Function<? super T,? extends R> mapper)

Но если учитывать тот факт, что тип не был указан, он будет приведён к виду:

Stream map(Function mapper)

Таким образом, в результате map() вернёт объект Stream. Что также помешает правильно отработать функции collect(), которая из вида:

<R> R collect(Supplier<R> supplier,
              BiConsumer<R,? super T> accumulator,
              BiConsumer<R,R> combiner)

Превратится в:

 Object collect(Supplier supplier,
                BiConsumer accumulator,
                BiConsumer combiner)

Тем самым теряется объявление List и List<String> соответственно. Что и вызывает ошибку компиляции.

В итоге можно привести данный объект к необходимому виду, однако данный вид приведения вызовет предупреждение unchecked casts, так как компилятор не знает, правильно ли вы привели тип.

Answer 2

Если вы используете raw type Stream stream, то generics-и пропадают во всех методах Stream, и метод collect в частности начинает возвращать просто Object. При желании, конечно, можно привести результат выполнения метода collect к List<String>:

List<String> collect = (List<String>)stream.map(obj -> obj.toString()) 
                                           .collect(Collectors.toList());

Аналогично с приведением списка к List<Object>: либо итоговый Stream будет параметризованным, либо окажется raw type с той же самой проблемой.

READ ALSO
Socket или Long polling в андроид ява

Socket или Long polling в андроид ява

Всем приветВ приложении хочу сделать чат администрации

187
Переход из одного фрагмента в другой при нажатии на кнопку в listview

Переход из одного фрагмента в другой при нажатии на кнопку в listview

У меня есть listvew с кастамным адаптером, в котором находится Textview, CheckBox и кнопкаЯ хочу чтобы при нажатии на imaginbutton imbutUpd, фрагмент где находится...

175
Оценка выстрела по мишени (Java, Android)

Оценка выстрела по мишени (Java, Android)

Пытаюсь реализовать оценку выстрела по мишениМишень вот такого типа:

184
Кoрректная работа z-index

Кoрректная работа z-index

Столкнулась с такой проблемой: не могу правильно задать элементам z-index, чтобы всё работало корректноВот тут код

227