Dans mon exemple, j'essaye de créer une table ASCII à partir d'une séquence de caractères. J'ai réussi à le faire avec une List
de chaînes mais j'ai échoué avec un tableau de caractères.
J'obtiens une erreur indiquant que Character :: hashCode
ne peut pas être résolu dans Collectors.toMap ()
.
public class JavaCollectToMapEx2 { public static void main(String[] args) { // list of ASCII characters var chars = List.of("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"); // CharSequence chars2 = "abcdefghijklmnopqrstuvwxyz"; char[] letters = "abcdefghijklmnopqrstuvwxyz".toCharArray(); // Map to represent ASCII character table Map<Integer, String> asciiMap = chars.stream() .collect(Collectors.toMap(String::hashCode, Function.identity())); Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars() .collect(Collectors.toMap(Character::hashCode, Function.identity())); System.out.println(asciiMap); System.out.println(asciiMap2); } }
Y a-t-il un moyen de le faire?
Error:(26, 17) java: method collect in interface java.util.stream.IntStream cannot be applied to given types; required: java.util.function.Supplier<R>,java.util.function.ObjIntConsumer<R>,java.util.function.BiConsumer<R,R> found: java.util.stream.Collector<java.lang.Object,capture#1 of ?,java.util.Map<java.lang.Object,java.lang.Object>> reason: cannot infer type-variable(s) R (actual and formal argument lists differ in length) Error:(26, 42) java: incompatible types: cannot infer type-variable(s) T,K,U,T (argument mismatch; invalid method reference incompatible types: java.lang.Object cannot be converted to char)
3 Réponses :
.chars ()
vous donne un IntStream
, qui est un flux de int
primitif, et non un flux de caractères ( plus d'infos ). C'est pourquoi aucune référence de méthode sur Character
ne fonctionnera.
Pour réaliser ce que vous recherchez, vous aurez d'abord besoin d'un Stream
:
Function<Character, Integer> f1 = e -> Character.hashCode(e); Function<Character, Integer> f2 = e -> e.hashCode();
Maintenant, vous avez toujours le problème de l'utilisation d'une référence de méthode pour obtenir le code de hachage. Vous ne pouvez pas utiliser Character :: hashCode
car il est ambigu de savoir quelle méthode vous voulez, car il y en a deux possibles:
int hashCode (char value)
Vous pouvez voir à partir de ce code, que les deux satisfont le premier argument de toMap()
:
Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters) .chars() .mapToObj(e -> (char) e) .collect(Collectors.toMap(e -> e.hashCode(), Function.identity()));
Pour résoudre ce problème , vous pouvez utiliser Object :: hashCode
pour l'appel de méthode non statique.
Le problème réel, concernant l'erreur du compilateur publiée, était que IntStream
n'a pas de méthode collect (Collector)
. Une alternative aurait été CharBuffer.wrap (lettres) .chars () .boxed () .collect (Collectors.toMap (Function.identity (), e -> (char) e));
Vous devez d'abord mapper le IntStream
à un Stream
. Mais après cela, vous ne pouvez pas utiliser la référence de méthode Character :: hashCode
car elle est ambiguë (niveau objet et niveau classe):
Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars() .mapToObj(i -> (char) i) .collect(Collectors.toMap(Object::hashCode, Function.identity()));
Sinon, vous pouvez simplement utiliser Object :: hashCode au lieu de i -> Character.hashCode (i)
car la classe Character
remplace son hashCode () code > méthode utilisant
Character.hashCode()
:
public final class Character ... { @Override public int hashCode() { return Character.hashCode(value); } }
Enfin, vous pouvez simplement utiliser ceci:
Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars() .mapToObj(i -> (char) i) .collect(Collectors.toMap(i -> Character.hashCode(i), Function.identity()));
Puisque vous utilisez la méthode collect ()
après CharBuffer :: chars
qui renvoie IntStream
, la seule méthode de collecte que vous pouvez utiliser est IntStream :: collect (fournisseur
prenant 3 paramètres.
Si vous souhaitez utiliser la méthode de collecte à un paramètre, placez IntStream :: boxed
avant de renvoyer Stream
. Ensuite, la méthode Character :: hashCode
devient ambiguë et l'expression lambda ne peut pas être utilisée:
Pour éviter cela, utilisez simplement une meilleure méthode mapToObj
pour convertir directement en char
sans avoir besoin de boxer, puis utiliser Object :: hashCode
hérité de `Object:
Map<Integer, Character> asciiMap2 = CharBuffer.wrap(letters).chars() .mapToObj(ch -> (char) ch) .collect(Collectors.toMap(Object::hashCode, Function.identity()));
et aucun message d'erreur ???
J'ai ajouté le message d'erreur complet.