web-dev-qa-db-fra.com

Remplacez ce lambda par une référence de méthode

J'ai le code suivant. Sonar se plaint de remplacer cette lambda par une référence de méthode.

Stream.iterate(0, i -> i + 1).limit(100).map(i -> Integer.toString(i));

Si je le remplace par le code ci-dessous, il ne se compile pas avec une erreur de compilation: incompatibilité de type: impossible de convertir à partir de Stream<Object> à <unknown>.

Stream.iterate(0, i -> i + 1).limit(100).map(Integer::toString);

Comment est Integer::toString conversion Stream<Object> à <unknown>?

11
fastcodejava

C'est ambigu car les méthodes statique et non statiquetoString() sont toutes deux compatibles avec la signature fonctionnelle Integer -> String. Vous pouvez utiliser String::valueOf au lieu.

8
shmosel

Vous ne pouvez pas mettre Integer::toString parce que Integer a deux implémentations qui correspondent à l'interface fonctionnelle Function<Integer, String>, mais vous pouvez utiliser String::valueOf au lieu:

Stream.iterate(0, i -> i + 1)
        .limit(100)
        .map(String::valueOf)
        .collect(Collectors.toList())
5
vlad324

Comme mentionné par @shmosel, remplacer déjà le lambda par une référence de méthode entraînera une ambiguïté car il existe deux méthodes toString de la signature:

parce que l'appel à Stream.iterate(0, i -> i + 1) renvoie un Stream<Integer> lorsque vous appelez map avec la référence de méthode Integer::toString le compilateur n'est pas sûr si vous vouliez faire Integer.toString(i) ou i.toString() d'où l'erreur de compilation.

Voici donc d'autres options par rapport à ce qui a déjà été fourni:

au lieu de Stream.iterate, vous pouvez utiliser IntStream.iterate puis appeler mapToObj:

IntStream.iterate(0, i -> i + 1) // IntStream
         .limit(100) // IntStream
         .mapToObj(Integer::toString); // i1 -> Integer.toString(i1)

Une autre chose suggérée par intelliJ est que vous pouvez réellement faire:

Stream.iterate(0, i -> i + 1) // Stream<Integer>
      .limit(100) // Stream<Integer>
      .map(Object::toString); // integer -> integer.toString()

Object::toString est équivalent à la lambda integer -> integer.toString()


sur une autre note, il est intéressant que Sonar propose de remplacer le lambda par une référence de méthode dans le code que vous avez montré. intelliJ IDEA était assez intelligent pour ne pas le suggérer.

2
Ousmane D.

Je pense que IntStream est meilleur pour votre code:

List<String> numbers = IntStream.range(0, 100)
                                .mapToObj(String::valueOf)
                                .collect(Collectors.toList());

Ou pour votre exemple, utilisez String.valueOf pour convertir int -> String:

List<String> numbers = Stream.iterate(0, i -> i + 1)
                             .limit(100)
                             .map(String::valueOf)
                             .collect(Collectors.toList());
0
oleg.cherednik