Java Academy · Oppitunti

Monikenttälajittelu thenComparing-metodilla

Ketjuta vertailijat thenComparing-metodilla lajitellaksesi useiden kenttien mukaan tärkeysjärjestyksessä.

Oppitunti 3/414 vaihetta

Monikenttälajittelu thenComparing-metodilla on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/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.

Järjestäminen usean avaimen perusteella

thenComparing() ketjuttaa Comparatorit usean kentän perusteella järjestämistä varten. Ensisijainen järjestys käsitellään ensin, sen jälkeen tasatilanteissa toissijainen ja niin edelleen.

thenComparing-perusteet

Käyttäkää thenComparing()-menetelmää tasatilanteiden ratkaisemiseen ensisijaisen Comparatorin jälkeen.

import java.util.*;

record Student(String name, int grade, double gpa) {}

List<Student> students = List.of(
    new Student("Alice",   10, 3.9),
    new Student("Bob",     11, 3.7),
    new Student("Charlie", 10, 3.8),
    new Student("Diana",   11, 3.7)
);

Comparator<Student> sort = Comparator.comparingInt(Student::grade)
    .thenComparingDouble(Student::gpa).reversed()
    .thenComparing(Student::name);

students.stream().sorted(sort).forEach(System.out::println);

Kolmitasoinen järjestäminen

Ketjuttakaa niin monta thenComparing-tasoa kuin tarvitaan.

record Employee(String dept, String team, String name, double salary) {}

List<Employee> employees = List.of(
    new Employee("Eng", "Backend", "Alice",   95000),
    new Employee("Eng", "Backend", "Bob",     92000),
    new Employee("Eng", "Frontend","Charlie", 88000),
    new Employee("Mkt", "Growth",  "Diana",   75000)
);

Comparator<Employee> sort = Comparator
    .comparing(Employee::dept)
    .thenComparing(Employee::team)
    .thenComparing(Comparator.comparingDouble(Employee::salary).reversed());

employees.stream().sorted(sort)
    .forEach(e -> System.out.printf("%s > %s > %s: $%.0f%n",
        e.dept(), e.team(), e.name(), e.salary()));

thenComparing Comparatorin kanssa

Käyttäkää Comparatorin hyväksyvää ylikuormitettua menetelmää, kun toissijaisille avaimille tarvitaan käänteinen tai mukautettu järjestys.

Comparator<Employee> sort = Comparator
    .comparing(Employee::dept)
    .thenComparing(Comparator.comparing(Employee::salary).reversed()); // highest paid first
    // equivalent: .thenComparingDouble(Employee::salary, Comparator.reverseOrder())

Null-arvoja sisältävien kenttien järjestäminen

Yhdistäkää thenComparing menetelmiin nullsLast tai nullsFirst, jotta valinnaiset kentät käsitellään hallitusti.

record Product(String name, String category, Double rating) {}

Comparator<Product> sort = Comparator
    .comparing(Product::category, Comparator.nullsLast(Comparator.naturalOrder()))
    .thenComparing(Product::rating,  Comparator.nullsLast(Comparator.reverseOrder()))
    .thenComparing(Product::name);

Järjestämisavaimen valinta ajonaikaisesti

Valitkaa järjestämisavain ajonaikaisesti käyttäjän asetuksen perusteella.

static Comparator<Product> sortBy(String key) {
    return switch (key) {
        case "price"    -> Comparator.comparingDouble(Product::price);
        case "name"     -> Comparator.comparing(Product::name);
        case "stock"    -> Comparator.comparingInt(Product::stock).reversed();
        default         -> Comparator.comparingDouble(Product::price);
    };
}

String userChoice = "stock";
products.stream().sorted(sortBy(userChoice)).forEach(System.out::println);

thenComparing poimijafunktion kanssa

thenComparing(Function<T,U>)-ylikuormitus poimii Comparable-avaimen toissijaista järjestystä varten ilman erillistä Comparatoria.

record Event(String type, int year, int month, int day) {}

Comparator<Event> chronological = Comparator
    .comparing(Event::type)
    .thenComparingInt(Event::year)
    .thenComparingInt(Event::month)
    .thenComparingInt(Event::day);

Tietuekokoelmien järjestäminen

Accessor-menetelmät sisältävät record-tyypit toimivat saumattomasti metodiviittausten kanssa Comparator-ketjuissa.

record Order(String customerId, String status, double total, java.time.LocalDate date) {}

List<Order> orders = loadOrders();

Comparator<Order> byCustomerThenDate = Comparator
    .comparing(Order::customerId)
    .thenComparing(Order::date, Comparator.reverseOrder()); // newest first per customer

orders.stream().sorted(byCustomerThenDate)
    .collect(Collectors.groupingBy(Order::customerId))
    .forEach((cust, ords) -> {
        System.out.println("Customer: " + cust);
        ords.forEach(o -> System.out.println("  " + o.date() + " $" + o.total()));
    });

Vakaa järjestystakuu

Javan List.sort() ja olioille tarkoitettu Arrays.sort() käyttävät vakaata lomitusjärjestämistä. Keskenään samanarvoisina vertautuvien alkioiden alkuperäinen keskinäinen järjestys säilyy.

// Stable sort example:
// First sort by name, then by dept
// Equal dept elements preserve the name order from previous sort
List<Employee> sorted = employees.stream()
    .sorted(Comparator.comparing(Employee::name))     // 1st pass
    .sorted(Comparator.comparing(Employee::dept))     // 2nd pass (stable!)
    .collect(Collectors.toList());
// Within each dept, employees remain alphabetically sorted

Comparator.comparing avain-Comparatorin kanssa

Kaksiparametrinen muoto Comparator.comparing(keyExtractor, keyComparator) mahdollistaa sekä avaimen että sen järjestyksen määrittämisen.

// Sort by name length, then alphabetically within same length
Comparator<String> c = Comparator
    .comparing(String::length, Integer::compare)
    .thenComparing(Comparator.naturalOrder());

List<String> words = new ArrayList<>(List.of("fig","apple","kiwi","banana","pea"));
words.sort(c);
System.out.println(words); // [fig, pea, kiwi, apple, banana]

Käytännön esimerkki: lentohakutulokset

Lentohakutulosten lajittelu hinnan, sitten keston ja lopuksi lähtöajan mukaan.

record Flight(String airline, double price, int durationMin, java.time.LocalTime departs) {}

Comparator<Flight> bestFlight = Comparator
    .comparingDouble(Flight::price)
    .thenComparingInt(Flight::durationMin)
    .thenComparing(Flight::departs);

Lajiteltujen tulosten kerääminen

Yhdistä usean avaimen lajittelu collectoreihin tuottaaksesi lajiteltuja ryhmiä tai karttoja.

Map<String, List<Employee>> byDept = employees.stream()
    .sorted(Comparator.comparing(Employee::dept)
        .thenComparing(Comparator.comparingDouble(Employee::salary).reversed()))
    .collect(Collectors.groupingBy(Employee::dept,
        LinkedHashMap::new,  // preserve insertion (sorted) order
        Collectors.toList()));

byDept.forEach((dept, emps) -> {
    System.out.println(dept + ":");
    emps.forEach(e -> System.out.println("  " + e.name() + " $" + e.salary()));
});

Pikatarkistus

Haluat lajitella työntekijät ensin osaston mukaan aakkosjärjestykseen ja sitten palkan mukaan laskevassa järjestyksessä. Mikä ketjutus on oikea?

Kertaus: usean avaimen lajittelu thenComparing()-menetelmällä

Tärkeimmät asiat:

  • thenComparing() lisää toissijaisia lajitteluavaimia, joita käytetään, kun ensisijaiset avaimet ovat yhtä suuret
  • Voit ketjuttaa niin monta thenComparing-tasoa kuin tarvitset
  • Käytä thenComparing(Comparator)-menetelmää yhdessä reversed()-menetelmän kanssa, kun toissijainen avain pitää lajitella laskevaan järjestykseen
  • Yhdistä nullsFirst- ja nullsLast-menetelmiin valinnaisia kenttiä varten
  • Javan List.sort() on vakaa — samanarvoiset alkiot säilyttävät alkuperäisen järjestyksensä
  • Dynaaminen lajittelun valinta: käytä switch-rakennetta palauttamaan oikea Comparator suorituksen aikana
Aloita maksutta

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 ”Monikenttälajittelu thenComparing-metodilla” ilmainen?

Kyllä – oppitunnin ”Monikenttälajittelu thenComparing-metodilla” 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 ”Monikenttälajittelu thenComparing-metodilla”?

Ketjuta vertailijat thenComparing-metodilla lajitellaksesi useiden kenttien mukaan tärkeysjärjestyksessä. 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 3/4.

Kuinka kauan ”Monikenttälajittelu thenComparing-metodilla”-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

  1. Comparable-rajapinta
  2. Comparator ja lajittelu lambdoilla
  3. Monikenttälajittelu thenComparing-metodilla
  4. Taulukoiden ja kokoelmien lajittelu käytännössä
← Takaisin: Java Academy