Un collecteur peut être utilisé pour cela.
- Pour deux catégories, utilisez l'
Collectors.partitioningBy()
usine.
Cela créera un Map
de Boolean
à List
et placera les éléments dans l'une ou l'autre liste basée sur un Predicate
.
Remarque: puisque le flux doit être consommé dans son intégralité, cela ne peut pas fonctionner sur des flux infinis. Et comme le flux est de toute façon consommé, cette méthode les place simplement dans des listes au lieu de créer un nouveau flux avec mémoire. Vous pouvez toujours diffuser ces listes si vous avez besoin de flux en sortie.
De plus, pas besoin de l'itérateur, même pas dans l'exemple de tête uniquement que vous avez fourni.
- Le fractionnement binaire ressemble à ceci:
Random r = new Random();
Map<Boolean, List<String>> groups = stream
.collect(Collectors.partitioningBy(x -> r.nextBoolean()));
System.out.println(groups.get(false).size());
System.out.println(groups.get(true).size());
- Pour plus de catégories, utilisez une
Collectors.groupingBy()
usine.
Map<Object, List<String>> groups = stream
.collect(Collectors.groupingBy(x -> r.nextInt(3)));
System.out.println(groups.get(0).size());
System.out.println(groups.get(1).size());
System.out.println(groups.get(2).size());
Dans le cas où les flux ne le sont pas Stream
, mais l'un des flux primitifs comme IntStream
, alors cette .collect(Collectors)
méthode n'est pas disponible. Vous devrez le faire de manière manuelle sans usine de collecte. Sa mise en œuvre ressemble à ceci:
[Exemple 2.0 depuis le 16/04/2020]
IntStream intStream = IntStream.iterate(0, i -> i + 1).limit(100000).parallel();
IntPredicate predicate = ignored -> r.nextBoolean();
Map<Boolean, List<Integer>> groups = intStream.collect(
() -> Map.of(false, new ArrayList<>(100000),
true , new ArrayList<>(100000)),
(map, value) -> map.get(predicate.test(value)).add(value),
(map1, map2) -> {
map1.get(false).addAll(map2.get(false));
map1.get(true ).addAll(map2.get(true ));
});
Dans cet exemple, j'initialise les ArrayLists avec la taille totale de la collection initiale (si cela est connu du tout). Cela empêche les événements de redimensionnement même dans le pire des cas, mais peut potentiellement engloutir 2 * N * T d'espace (N = nombre initial d'éléments, T = nombre de threads). Pour faire un compromis entre l'espace et la vitesse, vous pouvez le laisser de côté ou utiliser votre meilleure estimation éclairée, comme le plus grand nombre d'éléments attendus dans une partition (généralement un peu plus de N / 2 pour une répartition équilibrée).
J'espère que je n'offense personne en utilisant une méthode Java 9. Pour la version Java 8, consultez l'historique des modifications.
Stream
en plusieursStream
s sans conversion intermédiaire , même si je pense que les personnes qui ont atteint cette question cherchent en fait le moyen d'y parvenir indépendamment de cette contrainte, qui est la réponse de Mark. Cela peut être dû au fait que la question du titre n'est pas la même que celle de la description .