0Pricing
Java Academy · Aula

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 op

counting() 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: 3

Particionando 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));  // 2

Mapa 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

  1. groupingBy: Classificação de Elementos
  2. partitioningBy e Contagem
  3. toMap, joining e summarizing
  4. Construção de um Collector Personalizado
← Voltar para Java Academy