Ce code fonctionne (pris dans la 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 un "type de retour incompatible String dans l'expression lambda".
Pourquoi ? Et comment résoudre ce problème?
Arrays.stream(int[])
crée un IntStream
, pas un Stream<Integer>
. Vous devez donc appeler mapToObj
au lieu de simplement map
, lorsque vous mappez un int
à un objet.
Cela devrait fonctionner comme prévu:
String commaSeparatedNumbers = Arrays.stream(numbers)
.mapToObj(i -> ((Integer) i).toString()) //i is an int, not an Integer
.collect(Collectors.joining(", "));
que vous pouvez aussi écrire:
String commaSeparatedNumbers = Arrays.stream(numbers)
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));
Arrays.stream(numbers)
crée un IntStream
sous le capot et l'opération de mappage sur un IntStream
nécessite un IntUnaryOperator
(c'est-à-dire une fonction int -> int
). La fonction de mappage que vous souhaitez appliquer ne respecte pas ce contrat et par conséquent l'erreur de compilation.
Vous auriez besoin d'appeler boxed()
avant pour obtenir un Stream<Integer>
(C'est ce que Arrays.asList(...).stream()
renvoie). Ensuite, appelez simplement map
comme vous l'avez fait dans le premier extrait.
Notez que si vous avez besoin de boxed()
suivi de map
, vous voudrez probablement utiliser mapToObj
directement.
L'avantage est que mapToObj
ne nécessite pas d'encadrer chaque valeur int
dans un objet Integer
; en fonction de la fonction de mappage que vous appliquez bien sûr; donc j'irais avec cette option qui est aussi plus courte à écrire.
Vous pouvez créer un flux entier en utilisant Arrays.stream (int []), vous pouvez appeler mapToObj
comme mapToObj(Integer::toString)
.
String csn = Arrays.stream(numbers) // your numbers array
.mapToObj(Integer::toString)
.collect(Collectors.joining(", "));
J'espère que cela t'aides..
Si le but de cet exemple et de cette question est de déterminer comment mapper des chaînes à un flux d'ints (par exemple, utiliser un flux d'ints pour accéder à un index dans un tableau de chaînes), vous pouvez également utiliser la boxe, puis un int (qui permettrait alors d'accéder à l'index du tableau).
int[] numbers = {0, 1, 2, 3};
String commaSeparatedNumbers = Arrays.stream(numbers)
.boxed()
.map((Integer i) -> Integer.toString((int)i))
.collect(Collectors.joining(", "));
L’appel .boxed () convertit votre IntStream (un flux d’entités primitives) en un flux (un flux d’objets - à savoir, des objets Integer) qui acceptera ensuite le retour d’un objet (ici un objet String). votre lambda. Ici, il ne s'agit que d'une représentation sous forme de chaîne du nombre à des fins de démonstration, mais il pourrait tout aussi bien (et plus concrètement) être n'importe quel objet chaîne - comme l'élément d'un tableau de chaînes, comme mentionné précédemment.
Je pensais que j'offrirais une autre possibilité. En programmation, il y a toujours plusieurs façons d'accomplir une tâche. Sachez-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 la méthode la plus auto-documentée.
Bon codage!
Pas de boxe, autant que je sache, et pas d'explosion de petites ficelles ajoutées au tas:
public static void main(String[] args) {
IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6);
String s = stream.collect(StringBuilder::new, (builder, n) -> builder.append(',').append(n), (x, y) -> x.append(',').append(y)).substring(1);
System.out.println(s);
}