J'utilise stream pour parcourir la liste et je souhaite le collecter dans la carte, mais j'obtiens une erreur de compilation:
L'expression de référence de méthode n'est pas attendue ici
Voici mon code
List<Person> personList = getPersons(); Map<String, Integer> personAgeMap = personList.stream() .collect(Collectors.toMap(Person::getFirstName + "_" + Person::getLastName, Person::getAge));
J'ai vérifié ces réponses:
mais ce ne sont pas ce que je recherche, j'ai également vu le type de référence de méthode.
Dans ce cas, il s'agit d'une méthode d'instance de type d'instance, comment puis-je avoir une instance de Personne dans les collectionneurs.
quelle pourrait être la solution possible ou est-ce même faisable de cette façon?
3 Réponses :
Vous ne pouvez pas faire cela, cela n'a aucun sens:
Collectors.toMap(person -> person.getFirstName() + "_" + person.getLastName()
Vous devez comprendre ce qu'est la signature de la méthode toMap . Pour garder les choses simples, disons que c'est:
Collectors.toMap(new Function<Person, String>() { public String apply(Person person) { return person.getFirstName() + "_" + person.getLastName(); } });
Vous voyez? keyMapper est un objet de type Function. La fonction prend une entrée (une personne) et renvoie une sortie (une chaîne). Vous devez donc fournir une fonction qui fait cela. Si vous écrivez
Person::getFirstName + "_" + Person::getLastName
alors c'est ... enfin rien, mais disons que dans le pire des cas, il pourrait s'agir d'une chaîne. Parce que vous concaténez 3 choses avec une chaîne. Ce n'est pas une fonction. Ce que vous voulez, c'est créer une fonction.
Vous pouvez donc faire ceci:
void toMap(Function<? super T,? extends K> keyMapper)
Le raccourci pour cela est:
Collectors.toMap(Person::getFirstName + "_" + Person::getLastName
Vous ne pouvez pas y utiliser de référence de méthode. Essayez plutôt un lambda.
p -> ((Function<Person, String>) Person::getFirstName).apply(p) + "_" + ((Function<Person, String>) Person::getLastName).apply(p)
Person :: getFirstName
et Person :: getLastName
sont des instances d'une interface fonctionnelle (jamais de String ), par exemple Supplier
ou Function
, et l'opérateur +
peut ' t être appliquée à eux.
De même, cela n'aurait pas beaucoup de sens, si vous étiez
Object o = new Object() + new Object();
Pour vous intriguer un peu
Collectors.toMap( p -> String.format("%s_%s", p.getFirstName(), p.getLastName()), Person::getAge )
Ce que vous dites est juste, mais je pensais que la façon dont nous attendons l'âge de la déclaration Person :: getAge de la même manière que j'attendais une sortie de chaîne de Person :: getFirstName et Person :: getLastName, puis j'appliquais la concaténation. Maintenant j'ai compris.
Les références de méthode sont utilisées pour référencer une méthode dans un lambda. Il n'appelle pas la méthode, il fournit ses références au lambda.
Ce qui signifie que vous ne pouvez pas utiliser la référence de méthode de la même manière que vous appelez la méthode, donc Person :: getFirstName + "_ "+ Person :: getLastName
n'est pas correct.
Donc, pour obtenir le résultat souhaité, vous pouvez simplement utiliser une expression lambda de base comme celle-ci:
List<Person> personList = getPersons(); Map<String, Integer> personAgeMap = personList.stream() .collect(Collectors.toMap(person -> person.getFirstName() + "_" + person.getLastName(), Person::getAge));
J'espère que je suis devenu utile.
Person :: getFirstName + "_" + Person :: getLastName
est une syntaxe invalide Je pense, vous ne pouvez pas concaténer des références de méthode à des chaînes