Java Academy · Lektion

partitioningBy og counting

Opdel en stream i to grupper med partitioningBy, og tæl elementer med counting.

Lektion 2 af 413 trin

partitioningBy og counting er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.

Grundlæggende om partitioningBy

Collectors.partitioningBy(predicate) opdeler et stream i præcis to grupper — true og false — og returnerer en 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 sammenlignet med filter

I modsætning til filter bevarer partitioningBy begge grupper samtidig — det er nyttigt, når du har brug for begge dele af opdelingen.

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());

Nedstrøms-collector med partitioningBy

Kombinér partitioningBy med en nedstrøms-collector på samme måde som 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));

counting()-collector

Collectors.counting() tæller antallet af elementer i streamet eller den nedstrømsgruppe, der behandles. Det er en praktisk ækvivalent til 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() som nedstrøms-collector

counting() er særligt nyttig som nedstrøms-collector for 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

Opdeling i navne

Udtræk navne fra hver partition ved hjælp af en mapping-nedstrøms-collector:

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));

Kombination af counting og summarizingInt

Collectors.summarizingInt() beregner antal, sum, minimum, maksimum og gennemsnit i én gennemløbning:

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());

Praktisk anvendelse: A/B-testopdeling

Opdel brugere i kontrol- og behandlingsgrupper til en A/B-test:

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

Frekvenskort med groupingBy + counting

Tæl forekomsterne af hvert element (frekvenskort for ord):

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 returnerer altid begge nøgler

I modsætning til groupingBy returnerer partitioningBy altid en Map med både nøglerne true og false — også hvis den ene gruppe er tom. Det forhindrer NullPointerExceptions ved 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]

Ydelse: Én gennemløbning

Både partitioningBy og counting fungerer i én gennemløbning af streamet — O(n). De kræver ikke sortering. Derfor er de langt mere effektive end at kalde filter to gange eller sortere før gruppering.

Hurtigt tjek

Hvad er returtypen for Collectors.partitioningBy(predicate)?

Opsummering: partitioningBy og counting

Vigtigste pointer:

  • partitioningBy opdeler i præcis to grupper (true/false)
  • Begge nøgler er altid til stede — ingen risiko for NPE som ved groupingBy
  • counting() tæller elementer og bruges som nedstrøms-collector for grupper
  • summarizingInt/Long/Double giver antal+sum+minimum+maksimum+gennemsnit i én gennemløbning
  • Alle fungerer i én O(n)-gennemløbning af streamet
Gratis at komme i gang

Lær Java med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
104
Lektioner
374

Ofte stillede spørgsmål

Er lektionen “partitioningBy og counting” gratis?

Ja — hele teksten til “partitioningBy og counting” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “partitioningBy og counting”?

Opdel en stream i to grupper med partitioningBy, og tæl elementer med counting. Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Java Academy?

Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.

Hvor lang tid tager lektionen “partitioningBy og counting”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Java Academy-lektion?

Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. groupingBy: klassificering af elementer
  2. partitioningBy og counting
  3. toMap, joining og summarizing
  4. Opbygning af en brugerdefineret collector
← Tilbage til Java Academy