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());