J'essaie de trouver un moyen simple dans Java 8 API de flux pour faire le regroupement, je viens avec cette manière complexe!
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Hello");
list.add("World");
Map<String, List<String>> collect = list.stream().collect(
Collectors.groupingBy(o -> o));
System.out.println(collect);
List<String[]> collect2 = collect
.entrySet()
.stream()
.map(e -> new String[] { e.getKey(),
String.valueOf(e.getValue().size()) })
.collect(Collectors.toList());
collect2.forEach(o -> System.out.println(o[0] + " >> " + o[1]));
J'apprécie votre contribution.
Je pense que vous cherchez juste le surcharge qui prend un autre Collector
pour spécifier quoi faire avec chaque groupe ... et ensuite Collectors.counting()
pour effectuer le comptage:
import Java.util.*;
import Java.util.stream.*;
class Test {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Hello");
list.add("World");
Map<String, Long> counted = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
System.out.println(counted);
}
}
Résultat:
{Hello=2, World=1}
(Il y a aussi la possibilité d'utiliser groupingByConcurrent
pour plus d'efficacité. Ce qu'il faut garder à l'esprit pour votre vrai code, s'il est sans danger dans votre contexte.)
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Hello");
list.add("World");
Map<String, List<String>> collect = list.stream()
.collect(Collectors.groupingBy(o -> o));
collect.entrySet()
.forEach(e -> System.out.println(e.getKey() + " - " + e.getValue().size()));
Voici des options légèrement différentes pour accomplir la tâche à accomplir.
en utilisant toMap
:
list.stream()
.collect(Collectors.toMap(Function.identity(), e -> 1, Math::addExact));
en utilisant Map::merge
:
Map<String, Integer> accumulator = new HashMap<>();
list.forEach(s -> accumulator.merge(s, 1, Math::addExact));
Voici un exemple de liste d'objets
Map<String, Long> requirementCountMap = requirements.stream().collect(Collectors.groupingBy(Requirement::getRequirementType, Collectors.counting()));
Voici la solution simple par StreamEx
StreamEx.of(list).groupingBy(Function.identity(), Collectors.countingInt());
Réduisez le code passe-partout: collect(Collectors.
Si vous êtes prêt à utiliser une bibliothèque tierce, vous pouvez utiliser la classe Collectors2
dans Eclipse Collections pour convertir List
en Bag
à l'aide de Stream
. A Bag
est une structure de données qui est construite pour le comptage .
Bag<String> counted =
list.stream().collect(Collectors2.countBy(each -> each));
Assert.assertEquals(1, counted.occurrencesOf("World"));
Assert.assertEquals(2, counted.occurrencesOf("Hello"));
System.out.println(counted.toStringOfItemToCount());
Sortie:
{World=1, Hello=2}
Dans ce cas particulier, vous pouvez simplement collect
le List
directement dans un Bag
.
Bag<String> counted =
list.stream().collect(Collectors2.toBag());
Vous pouvez également créer Bag
sans utiliser Stream
en adaptant List
avec les protocoles de collections Eclipse.
Bag<String> counted = Lists.adapt(list).countBy(each -> each);
ou dans ce cas particulier:
Bag<String> counted = Lists.adapt(list).toBag();
Vous pouvez également simplement créer le sac directement.
Bag<String> counted = Bags.mutable.with("Hello", "Hello", "World");
Un Bag<String>
est comme un Map<String, Integer>
en ce sens qu'il garde en interne le suivi des clés et de leur nombre. Mais si vous demandez à Map
une clé qu’elle ne contient pas, elle renverra null
. Si vous demandez à une clé Bag
qu'elle ne contient pas avec occurrencesOf
, elle retournera 0.
Remarque: Je suis un partisan des collections Eclipse.