IntStream rangeClosed не может вернуть значение, отличное от int
Почему это ошибка? Я думал, что map
может вернуть любое значение.
var s = IntStream.rangeClosed(1, 5).map(String::valueOf).collect(Collectors.toList());
| Ошибка: | несовместимые типы: неверный тип возврата в ссылке на метод | java.lang.String не может быть преобразовано в int | var s = IntStream.rangeClosed(1, 5).map(String :: valueOf).collect(Collectors.toList()); |
^ ------------- ^
Ответы
Ответ 1
Используйте mapToObj:
var s = IntStream.rangeClosed(1, 5).mapToObj(String::valueOf).collect(Collectors.toList());
Карта из IntStream
может только сопоставить int
значение другого int
значение. Он принимает IntUnaryOperator
(который принимает int
и возвращает int
) в качестве функции отображения и возвращает IntStream
.
С другой стороны, mapToObj
позволяет вам сопоставить значение int
с любым ссылочным типом и, таким образом, преобразовать IntStream
в Stream<SomeReferenceType>
. Он принимает IntFunction<? extends U>
IntFunction<? extends U>
(который принимает int
и возвращает ссылочный тип) в качестве функции отображения и возвращает Stream<U>
.
Ответ 2
Вместо этого используйте mapToObj:
IntStream.rangeClosed(1, 5).mapToObj(String::valueOf).collect(Collectors.toList());
Ответ 3
Хотя вышеупомянутые ответы верны и mapToObj
является идиоматическим подходом, я считаю важным понять, почему возникает проблема, и, таким образом, в будущих случаях вы узнаете, как ее решить, просто изучив документацию.
это очень важный навык для программиста копаться в документации, когда он не понимает работу конкретного метода.
Итак, давайте пройдемся по соответствующим операциям потокового конвейера:
IntStream.rangeClosed
возвращает IntStream
в соответствии с документацией:
Возвращает последовательный упорядоченный IntStream из startInclusive (включительно) в endInclusive (включительно) с шагом 1.
ожидается, что IntStream
map
в IntStream
вернет IntStream
в соответствии с документацией:
Возвращает поток, состоящий из результатов применения данной функции к элементам этого потока.
Также важно отметить, что объявление метода для map
выглядит следующим образом:
IntStream map(IntUnaryOperator mapper)
то есть он принимает IntUnaryOperator
который фактически представляет операцию над одним int-значным операндом, который дает int-значный результат.
Однако вы передаете функцию String::valueOf
которая потребляет int
поскольку мы имеем дело с IntStream
и возвращает String
таким образом, несовместимую с IntUnaryOperator
и это является причиной проблемы.
Всякий раз, когда вы хотите взять специализацию примитивного потока и выполнить некоторую функцию отображения и, в свою очередь, получить в результате Stream<R>
тогда mapToObj
- это путь.
mapToObj
объявлен как:
mapToObj(IntFunction<? extends U> mapper)
IntFunction
представляет функцию, которая принимает аргумент типа int и выдает результат, который имеет тип R
что означает, что у вас будет Stream<R>
после mapToObj
.
Ответ 4
В качестве альтернативы вы можете использовать IntStream.boxed
как:
var s = IntStream.rangeClosed(1, 5) // IntStream
.boxed() // Stream<Integer>
.map(String::valueOf) // Stream<String>
.collect(Collectors.toList());
поскольку IntStream
изначально является последовательностью примитивных элементов int-values.
Другим вариантом выполнения такой операции будет:
var s = IntStream.rangeClosed(1, 5)
.boxed()
.map(a -> Integer.toString(a))
.collect(Collectors.toList());