partitioningBy ja counting
Jaa stream kahdeksi ryhmäksi partitioningBy-metodilla ja laske alkiot counting-metodilla.
partitioningBy ja counting on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
partitioningByn perusteet
Collectors.partitioningBy(predicate) jakaa streamin täsmälleen kahteen ryhmään — true ja false — ja palauttaa Map<Boolean, List<T>>-rakenteen.
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 ja filter
Toisin kuin filter, partitioningBy säilyttää molemmat ryhmät samanaikaisesti. Tämä on hyödyllistä, kun tarvitsette osituksen molemmat puolet.
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());Downstream partitioningByn kanssa
Yhdistäkää partitioningBy downstream-kerääjään samalla tavalla kuin 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()-kerääjä
Collectors.counting() laskee streamin (tai downstream-ryhmän) alkioiden määrän. Se on kätevä vastine lausekkeelle 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() downstream-kerääjänä
counting() on erityisen hyödyllinen groupingBy- ja partitioningBy-operaatioiden downstream-kerääjänä:
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: 3Osittelu nimien perusteella
Poimikaa nimet kustakin osituksesta mapping-downstream-kerääjän avulla:
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));countingin ja summarizingIntin yhdistäminen
Collectors.summarizingInt() laskee yhdellä läpikäynnillä määrän, summan, pienimmän ja suurimman arvon sekä keskiarvon:
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());Todellinen käyttötapaus: A/B-testin jako
Jakakaa käyttäjät kontrolli- ja käsittelyryhmiin A/B-testiä varten:
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)); // 2Frekvenssikartta groupingBy + counting -yhdistelmällä
Laskekaa kunkin alkion esiintymät eli muodostakaa sanojen frekvenssikartta:
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 palauttaa aina molemmat avaimet
Toisin kuin groupingBy, partitioningBy palauttaa aina map-rakenteen, jossa ovat sekä true- että false-avaimet, vaikka toinen ryhmistä olisi tyhjä. Näin vältetään NullPointerException map.get(true)-kutsussa.
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]Suorituskyky: yksi läpikäynti
Sekä partitioningBy että counting toimivat yhdellä streamin läpikäynnillä — O(n). Ne eivät edellytä järjestämistä. Siksi ne ovat huomattavasti tehokkaampia kuin filter-metodin kutsuminen kahdesti tai tietojen järjestäminen ennen ryhmittelyä.
Pikatarkistus
Mikä on Collectors.partitioningBy(predicate)-metodin palautustyyppi?
Kertaus: partitioningBy ja counting
Keskeiset opit:
- partitioningBy jakaa alkiot täsmälleen kahteen ryhmään (true/false)
- Molemmat avaimet ovat aina mukana, joten NPE-riskiä ei ole toisin kuin groupingBy-operaatiossa
- counting() laskee alkiot, ja sitä voi käyttää ryhmien downstream-kerääjänä
- summarizingInt/Long/Double tuottaa määrän, summan, minimiarvon, maksimiarvon ja keskiarvon yhdellä läpikäynnillä
- Kaikki toimivat yhdellä O(n)-suorituskyvyn stream-läpikäynnillä
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”partitioningBy ja counting” ilmainen?
Kyllä – oppitunnin ”partitioningBy ja counting” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”partitioningBy ja counting”?
Jaa stream kahdeksi ryhmäksi partitioningBy-metodilla ja laske alkiot counting-metodilla. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.
Kuinka kauan ”partitioningBy ja counting”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- groupingBy: alkioiden luokittelu
- partitioningBy ja counting
- toMap, joining ja summarizing
- Mukautetun kerääjän rakentaminen