Este código funciona (tomado en el Javadoc):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
.map(i -> i.toString())
.collect(Collectors.joining(", "));
Este no se puede compilar:
int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
.map((Integer i) -> i.toString())
.collect(Collectors.joining(", "));
IDEA me dice que tengo un "tipo de retorno incompatible String en expresión lambda".
Por qué ? ¿Y cómo solucionarlo?
java
functional-programming
java-8
java-stream
Denys Séguret
fuente
fuente
IntStream
yStream<Integer>
?IntStream
es una especialización de flujo paraint
valores primitivos . AStream<Integer>
es solo un Stream que contieneInteger
objetos.IntStream
es una corriente o primitivas (ints) mientras queSteram<Integer>
es una corriente de objetos. Las corrientes primitivas tienen métodos especializados por motivos de rendimiento.IntStream.mapToObj
espera unaIntFunction
, una función que consume unint
valor, por.mapToObj((Integer i) -> i.toString())
lo tanto , no funciona. De todos modos, no se recomendaría ya que contiene una conversión innecesaria deint
aInteger
. Por el contrario,.mapToObj(Integer::toString)
funciona bien ya que llamará alstatic
métodoInteger.toString(int)
. Tenga en cuenta que esto es diferente a llamar.map(Integer::toString)
a a,Stream<Integer>
ya que este último no se compilará porque es ambiguo..map(Integer::toString)
en unaStream<Integer>
es realmente ambigua ya que ambos,.map(i->i.toString())
y.map(i->Integer.toString(i))
son válidos. Pero se puede solucionar fácilmente usando.map(Object::toString)
.Arrays.stream(numbers)
crea unIntStream
bajo el capó y la operación del mapa en unIntStream
requiere unIntUnaryOperator
(es decir, una funciónint -> int
). La función de mapeo que desea aplicar no respeta este contrato y, por lo tanto, el error de compilación.Debería llamar
boxed()
antes para obtener unStream<Integer>
(esto es lo queArrays.asList(...).stream()
devuelve). Luego, simplemente llamemap
como lo hizo en el primer fragmento.Tenga en cuenta que si necesita
boxed()
seguido demap
probablemente desee utilizarmapToObj
directamente.La ventaja es que
mapToObj
no requiere encasillar cadaint
valor en unInteger
objeto; dependiendo de la función de mapeo que aplique, por supuesto; así que optaría por esta opción, que también es más corta de escribir.fuente
Puede crear un Integer Stream usando Arrays.stream (int []), puede llamar a
mapToObj
likemapToObj(Integer::toString)
.Espero que esto ayude..
fuente
Sin boxeo, AFAIK, y sin explosión de pequeñas cuerdas agregadas al montón:
fuente
Si el propósito de esta muestra y pregunta es averiguar cómo asignar cadenas a una secuencia de ints (por ejemplo, usar una secuencia de ints para acceder a un índice en una matriz de cadenas), también puede usar el boxeo y luego enviar a un int (que luego permitiría acceder al índice de la matriz).
La llamada .boxed () convierte su IntStream (una secuencia de entradas primitivas) en una secuencia (una secuencia de objetos, es decir, objetos Integer) que luego aceptará la devolución de un objeto (en este caso, un objeto String) de tu lambda. Aquí es solo una representación de cadena del número con fines de demostración, pero podría ser con la misma facilidad (y de manera más práctica) cualquier objeto de cadena, como el elemento de una matriz de cadenas como se mencionó anteriormente.
Solo pensé en ofrecer otra posibilidad. En programación, siempre hay múltiples formas de realizar una tarea. Conozca tantos como pueda, luego elija el que mejor se adapte a la tarea en cuestión, teniendo en cuenta los problemas de rendimiento, la intuición, la claridad del código, sus preferencias en el estilo de codificación y la mayor documentación posible.
¡Feliz codificación!
fuente
int
en su tipo de envoltorioInteger
y lo desempaqueta justo después.