web-dev-qa-db-fra.com

Joignez une liste de propriétés d'objet dans une chaîne

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?

23
winhell

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(","));
28
Aomine

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(","))));
1
holi-java

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;
1
Malte Hartwig