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

IntStreamyStream<Integer>?IntStreames una especialización de flujo paraintvalores primitivos . AStream<Integer>es solo un Stream que contieneIntegerobjetos.IntStreames 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.mapToObjespera unaIntFunction, una función que consume unintvalor, por.mapToObj((Integer i) -> i.toString())lo tanto , no funciona. De todos modos, no se recomendaría ya que contiene una conversión innecesaria deintaInteger. Por el contrario,.mapToObj(Integer::toString)funciona bien ya que llamará alstaticmé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 unIntStreambajo el capó y la operación del mapa en unIntStreamrequiere 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 llamemapcomo lo hizo en el primer fragmento.Tenga en cuenta que si necesita
boxed()seguido demapprobablemente desee utilizarmapToObjdirectamente.La ventaja es que
mapToObjno requiere encasillar cadaintvalor en unIntegerobjeto; 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
mapToObjlikemapToObj(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
inten su tipo de envoltorioIntegery lo desempaqueta justo después.