Ce code fonctionne (pris dans le Javadoc):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
.map(i -> i.toString())
.collect(Collectors.joining(", "));
Celui-ci ne peut pas être compilé:
int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
.map((Integer i) -> i.toString())
.collect(Collectors.joining(", "));
IDEA me dit que j'ai une "chaîne de type de retour incompatible dans l'expression lambda".
Pourquoi ? Et comment y remédier?
java
functional-programming
java-8
java-stream
Denys Séguret
la source
la source
IntStream
etStream<Integer>
?IntStream
est une spécialisation de flux pour lesint
valeurs primitives . AStream<Integer>
est juste un Stream contenant desInteger
objets.IntStream
est un flux ou des primitives (ints) alors queSteram<Integer>
c'est un flux d'objets. Les flux primitifs ont des méthodes spécialisées pour des raisons de performances.IntStream.mapToObj
attend anIntFunction
, une fonction qui consomme uneint
valeur, donc.mapToObj((Integer i) -> i.toString())
ne fonctionne pas. Cela ne serait de toute façon pas recommandé car il contient une conversion inutile deint
versInteger
. En revanche,.mapToObj(Integer::toString)
fonctionne bien car il appellera lastatic
méthodeInteger.toString(int)
. Notez que c'est différent de l'appel.map(Integer::toString)
à aStream<Integer>
car ce dernier ne se compilera pas car il est ambigu..map(Integer::toString)
aStream<Integer>
est vraiment ambigu comme les deux.map(i->i.toString())
et.map(i->Integer.toString(i))
est valide. Mais il est facilement résolu en utilisant.map(Object::toString)
.Arrays.stream(numbers)
crée unIntStream
sous le capot et l'opération cartographique sur unIntStream
nécessite unIntUnaryOperator
(c'est-à-dire une fonctionint -> int
). La fonction de mappage que vous souhaitez appliquer ne respecte pas ce contrat et donc l'erreur de compilation.Vous devrez appeler
boxed()
avant pour obtenir unStream<Integer>
(c'est ce quiArrays.asList(...).stream()
revient). Ensuite, appelez simplementmap
comme vous l'avez fait dans le premier extrait.Notez que si vous avez besoin de
boxed()
suivi parmap
vous souhaitez probablement utilisermapToObj
directement.L'avantage est qu'il
mapToObj
n'est pas nécessaire de placer chaqueint
valeur dans unInteger
objet; en fonction de la fonction de cartographie que vous appliquez bien sûr; donc j'irais avec cette option qui est également plus courte à écrire.la source
Vous pouvez créer un flux entier en utilisant Arrays.stream (int []), vous pouvez appeler
mapToObj
likemapToObj(Integer::toString)
.J'espère que cela t'aides..
la source
Pas de boxe, AFAIK, et pas d'explosion de petites cordes ajoutées au tas:
la source
Si le but de cet exemple et de cette question est de comprendre comment mapper des chaînes à un flux d'entiers (par exemple, en utilisant un flux d'entiers pour accéder à un index dans un tableau de chaînes), vous pouvez également utiliser la boxe, puis la conversion en un int (qui permettrait alors d'accéder à l'index du tableau).
L'appel .boxed () convertit votre IntStream (un flux d'entiers primitifs) en un Stream (un flux d'objets - à savoir, des objets Integer) qui acceptera alors le retour d'un objet (dans ce cas, un objet String) de votre lambda. Ici, il s'agit simplement d'une représentation sous forme de chaîne du nombre à des fins de démonstration, mais cela pourrait tout aussi facilement (et plus pratiquement) être n'importe quel objet de chaîne - comme l'élément d'un tableau de chaînes comme mentionné précédemment.
Je pensais juste offrir une autre possibilité. En programmation, il existe toujours plusieurs façons d'accomplir une tâche. Apprenez-en autant que vous le pouvez, puis choisissez celui qui convient le mieux à la tâche à accomplir, en gardant à l'esprit les problèmes de performances, l'intuitivité, la clarté du code, vos préférences en matière de style de codage et le plus auto-documenté.
Bon codage!
la source
int
à son type de wrapperInteger
et vous le déballez juste après.