web-dev-qa-db-fra.com

Collection à diffuser dans une nouvelle collection

Je recherche le moyen le plus simple de filtrer une collection. Je pense à quelque chose comme

Collection<?> foo = existingCollection.stream().filter( ... ). ...

Mais je ne sais pas quel est le meilleur moyen de passer du filtre à la restitution ou au remplissage d'une autre collection. La plupart des exemples semblent être "et ici vous pouvez imprimer". Il est possible qu'il y ait un constructeur ou une méthode de sortie qui me manque.

46
xenoterracide

Il existe une raison pour laquelle la plupart des exemples évitent de stocker le résultat dans un Collection. Ce n’est pas la méthode de programmation recommandée. Vous avez déjà un Collection, celui qui fournit les données source et les collections ne sert à rien. Vous voulez effectuer certaines opérations dessus. Le cas idéal est donc d'exécuter l'opération à l'aide du flux et de ne pas stocker les données dans un Collection intermédiaire. C’est ce que la plupart des exemples essaient de suggérer.

Bien sûr, de nombreuses API existantes fonctionnent avec Collections et le resteront toujours. Ainsi, l’API Stream offre différentes manières de gérer la demande d’un objet Collection.

  • Obtenez une implémentation List arbitraire contenant le résultat:

    List<T> results = l.stream().filter(…).collect(Collectors.toList());
    
  • Obtenez une implémentation Set arbitraire contenant le résultat:

    Set<T> results = l.stream().filter(…).collect(Collectors.toSet());
    
  • Obtenir un Collection spécifique:

    ArrayList<T> results =
      l.stream().filter(…).collect(Collectors.toCollection(ArrayList::new));
    
  • Ajouter à un Collection existant:

    l.stream().filter(…).forEach(existing::add);
    
  • Créer un tableau:

    String[] array=l.stream().filter(…).toArray(String[]::new);
    
  • Utilisez le tableau pour créer une liste avec un comportement spécifique (taille modifiable et fixe):

    List<String> al=Arrays.asList(l.stream().filter(…).toArray(String[]::new));
    
  • Autorisez un flux capable parallèle à ajouter des listes locales temporaires et à les joindre ensuite:

    List<T> results
      = l.stream().filter(…).collect(ArrayList::new, List::add, List::addAll);
    

    (Remarque: ceci est étroitement lié à la façon dont Collectors.toList() est actuellement implémenté, mais c'est un détail d'implémentation, c'est-à-dire qu'il n'y a aucune garantie que les implémentations futures des collecteurs toList() renverront toujours un ArrayList)

114
Holger

Un exemple tiré de la documentation de Java.util.stream:

List<String>results =
     stream.filter(s -> pattern.matcher(s).matches())
           .collect(Collectors.toList());

Collectors a une méthode toCollection(), je suggérerais de regarder de cette façon.

4
Samy Dindane

Par exemple, cela correspond davantage au style de programmation fonctionnelle Java 8:

Collection<String> a = Collections.emptyList();
List<String> result = a.stream().
     filter(s -> s.length() > 0).
     collect(Collectors.toList());
3
nobeh