web-dev-qa-db-fra.com

Pourquoi ne puis-je pas mapper des entiers sur des chaînes lors de la diffusion à partir d'un tableau?

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?

83
Denys Séguret

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(", "));
104
assylias

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.

19
Alexis C.

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..

5
codebot

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!

1
jamesc1101

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);
}
0
AbuNassar