partitioningBy e Contagem
Divida um fluxo em dois grupos com partitioningBy e conte os elementos com counting.
partitioningBy e Contagem é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.
Noções básicas de partitioningBy
Collectors.partitioningBy(predicate) divide um fluxo em exatamente dois grupos — true e false — e retorna um Map<Boolean, List<T>>.
import java.util.*;
import java.util.stream.*;
List<Integer> nums = List.of(1,2,3,4,5,6,7,8,9,10);
Map<Boolean, List<Integer>> evenOdd =
nums.stream().collect(Collectors.partitioningBy(n -> n % 2 == 0));
System.out.println(evenOdd.get(true)); // [2, 4, 6, 8, 10]
System.out.println(evenOdd.get(false)); // [1, 3, 5, 7, 9]partitioningBy versus filter
Diferentemente de filter, partitioningBy mantém os dois grupos simultaneamente — algo útil quando você precisa das duas partes da divisão.
record Student(String name, int score) {}
List<Student> students = List.of(
new Student("Alice",90), new Student("Bob",55),
new Student("Carol",72), new Student("Dave",48)
);
Map<Boolean, List<Student>> result =
students.stream().collect(
Collectors.partitioningBy(s -> s.score() >= 60)
);
System.out.println("Passed: " + result.get(true).size());
System.out.println("Failed: " + result.get(false).size());Coletor subsequente com partitioningBy
Combine partitioningBy com um coletor subsequente, assim como faria com groupingBy:
Map<Boolean, Long> passFailCount =
students.stream().collect(
Collectors.partitioningBy(
s -> s.score() >= 60,
Collectors.counting()
)
);
System.out.println("Passed: " + passFailCount.get(true));
System.out.println("Failed: " + passFailCount.get(false));Coletor counting()
Collectors.counting() conta o número de elementos no fluxo ou no grupo subsequente. É uma forma conveniente equivalente a reducing(0L, e -> 1L, Long::sum).
long count = Stream.of("a","bb","ccc","dddd")
.collect(Collectors.counting());
System.out.println(count); // 4
// Same as:
long count2 = Stream.of("a","bb","ccc","dddd").count();
// Use counting() as a downstream; use .count() as a terminal opcounting() como coletor subsequente
counting() é especialmente útil como coletor subsequente para groupingBy/partitioningBy:
List<String> words = List.of("cat","dog","car","door","cup","dune");
Map<Character, Long> byFirstLetter =
words.stream().collect(
Collectors.groupingBy(w -> w.charAt(0), Collectors.counting())
);
byFirstLetter.forEach((c, n) -> System.out.println(c + ": " + n));
// c: 3, d: 3Particionando em nomes
Extraia os nomes de cada partição usando um coletor mapping subsequente:
Map<Boolean, List<String>> namesByPass =
students.stream().collect(
Collectors.partitioningBy(
s -> s.score() >= 60,
Collectors.mapping(Student::name, Collectors.toList())
)
);
System.out.println("Passed: " + namesByPass.get(true));
System.out.println("Failed: " + namesByPass.get(false));Combinando counting com summarizingInt
Collectors.summarizingInt() calcula contagem, soma, mínimo, máximo e média em uma única passagem:
IntSummaryStatistics stats =
students.stream().collect(
Collectors.summarizingInt(Student::score)
);
System.out.println("Count: " + stats.getCount());
System.out.println("Average: " + stats.getAverage());
System.out.println("Max: " + stats.getMax());
System.out.println("Min: " + stats.getMin());Caso real: divisão de teste A/B
Particione os usuários em grupos de controle e tratamento para um teste A/B:
record User(String id, boolean isInTreatment) {}
List<User> users = List.of(
new User("u1",true), new User("u2",false),
new User("u3",true), new User("u4",false)
);
Map<Boolean, Long> split =
users.stream().collect(
Collectors.partitioningBy(User::isInTreatment, Collectors.counting())
);
System.out.println("Treatment: " + split.get(true)); // 2
System.out.println("Control: " + split.get(false)); // 2Mapa de frequências com groupingBy + counting
Conte as ocorrências de cada elemento, criando um mapa de frequência de palavras:
List<String> words2 = List.of("apple","banana","apple","cherry","banana","apple");
Map<String, Long> freq =
words2.stream().collect(
Collectors.groupingBy(w -> w, Collectors.counting())
);
freq.entrySet().stream()
.sorted(Map.Entry.<String,Long>comparingByValue().reversed())
.forEach(e -> System.out.println(e.getKey()+": "+e.getValue()));partitioningBy sempre retorna as duas chaves
Diferentemente de groupingBy, partitioningBy sempre retorna um mapa com as chaves true e false — mesmo quando um dos grupos está vazio. Isso evita NullPointerExceptions em map.get(true).
List<Integer> allEven = List.of(2,4,6);
Map<Boolean, List<Integer>> m =
allEven.stream().collect(Collectors.partitioningBy(n -> n % 2 != 0));
System.out.println(m.get(true)); // [] (empty, not null)
System.out.println(m.get(false)); // [2, 4, 6]Desempenho: passagem única
Tanto partitioningBy quanto counting operam em uma única passagem pelo fluxo — O(n). Eles não exigem ordenação. Isso os torna muito mais eficientes do que chamar filter duas vezes ou ordenar antes de agrupar.
Verificação rápida
Qual é o tipo de retorno de Collectors.partitioningBy(predicate)?
Recapitulação: partitioningBy e counting
Principais pontos:
- partitioningBy divide os dados em exatamente dois grupos (true/false)
- As duas chaves estão sempre presentes — não há risco de NPE, ao contrário do que ocorre com groupingBy
- counting() conta os elementos; use-o como coletor subsequente para grupos
- summarizingInt e equivalentes para valores inteiros e de ponto flutuante fornecem contagem, soma, mínimo, máximo e média em uma única passagem
- Todas essas operações funcionam em uma única passagem O(n) pelo fluxo
Perguntas Frequentes
A aula “partitioningBy e Contagem” é grátis?
Sim — o texto completo de “partitioningBy e Contagem” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.
O que vou aprender em “partitioningBy e Contagem”?
Divida um fluxo em dois grupos com partitioningBy e conte os elementos com counting. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Java Academy?
Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “partitioningBy e Contagem”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Java Academy?
Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- groupingBy: Classificação de Elementos
- partitioningBy e Contagem
- toMap, joining e summarizing
- Construção de um Collector Personalizado