J'apprends lambda en ce moment, et je me demande comment puis-je écrire ce code par une seule ligne avec lambda.
J'ai une classe Person
qui comprend les champs ID
et name
Actuellement, j'ai un List<Person>
qui stocke ces Person
objets. Ce que je veux accomplir, c'est obtenir une chaîne composée de l'identifiant de la personne comme.
"id1, id2, id3".
Comment puis-je accomplir cela avec lambda?
Pour récupérer un String
composé de tous les ID séparés par le délimiteur ","
vous devez d'abord map
les Person
ID dans un nouveau flux que vous pouvez ensuite appliquer Collectors.joining
activé.
String result = personList.stream().map(Person::getId)
.collect(Collectors.joining(","));
si votre champ ID n'est pas un String
mais plutôt un int
ou un autre type numérique primitif, vous devez utiliser la solution ci-dessous:
String result = personList.stream().map(p -> String.valueOf(p.getId()))
.collect(Collectors.joining(","));
diffuser sur la carte et collecter sur la liste!
List<String> myListofPersons = personList.stream()
.map(Person::getId)
.collect(Collectors.toList());
si vous en avez besoin dans un objet String, rejoignez la liste
String res = String.join(" , ", myListStringId);
System.out.println(res);
Vous pouvez également utiliser Collectors # mapping comme ci-dessous:
String ids = personList.stream().collect(mapping(Person::getId
, Collectors.joining(",")));
[~ # ~] ou [~ # ~] Person.ID
n'est pas une instance de CharSequence
alors vous avez besoin d'un double mappage comme ci-dessous:
String ids = personList.stream().collect(mapping(Person::getId
, mapping(String::valueOf
, Collectors.joining(","))));
Légèrement sur-conçu, mais utile à avoir si ce problème se produit plus souvent (surtout si vous ajoutez des méthodes surchargées qui délèguent à celle-ci à l'aide de mappeurs et de séparateurs par défaut):
/**
* @param separator used to join the values. NOTE: the separator is interpreted as a regular expression.
* @return a list of the values' string representation according to <code>mapper</code>, separated by the specified
* string. Null if list is null or empty.
*/
public static <R> String toListString(Collection<R> list, String separator,
Function<? super R, ? extends String> mapper)
{
if (list == null || list.isEmpty())
{
return null;
}
return list.stream()
.map(mapper)
.collect(Collectors.joining(separator));
}
et la fonction inverse appropriée:
/**
* @param list a list of values, separated by the specified separator
* @param separator used to join the values. NOTE: the separator is interpreted as a regular expression.
* @param mapper the function to map a single string to a value.
* @return a list of the values. Empty if string is null or empty.
*/
public static <R> List<R> fromListString(String list, String separator,
Function<? super String, ? extends R> mapper)
{
if (list == null || list.isEmpty())
{
return new ArrayList<>();
}
return Arrays.stream(list.trim().split(separator))
.map(mapper)
.collect(Collectors.toCollection(ArrayList::new));
}
Si les performances sont un problème, j'opterais pour l'approche en boucle classique:
StringBuilder s = new StringBuilder();
for(R r : list){
if (s.length() != 0)
s.append(separator);
s.append(mapper.apply(r));
}
return s.toString();
et:
List<R> result = new ArrayList<>();
for (String s : list.trim().split(separator)){
result.add(mapper.apply(s));
}
return result;