0Pricing
Java Academy · Lekcja

Comparator i sortowanie za pomocą lambd

Twórz obiekty Comparator za pomocą wyrażeń lambda i fabrycznych metod Comparator.comparing.

Comparator i sortowanie za pomocą lambd to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 2 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

Comparator i sortowanie za pomocą lambd

Comparator<T> definiuje zewnętrzny porządek obiektów. W przeciwieństwie do Comparable można utworzyć dowolną liczbę komparatorów bez modyfikowania klasy.

Tworzenie komparatorów

Komparator można utworzyć za pomocą lambdy lub odwołania do metody, a następnie przekazać go do metod sortujących.

import java.util.*;

record Product(String name, double price, int stock) {}

List<Product> products = new ArrayList<>(List.of(
    new Product("Mouse",    29.99, 50),
    new Product("Laptop",  999.00, 5),
    new Product("USB Hub",  24.99, 100)
));

// Lambda comparator
products.sort((a, b) -> Double.compare(a.price(), b.price()));
System.out.println(products);
// [USB Hub, Mouse, Laptop] (by price ascending)

Fabryka Comparator.comparing

Comparator.comparing(keyExtractor) tworzy Comparator na podstawie funkcji ekstrakcji klucza — jest to czytelniejsze niż używanie surowych lambd.

import java.util.Comparator;

Comparator<Product> byPrice = Comparator.comparingDouble(Product::price);
Comparator<Product> byName  = Comparator.comparing(Product::name);
Comparator<Product> byStock = Comparator.comparingInt(Product::stock);

products.sort(byPrice);
System.out.println(products); // sorted by price ascending

products.sort(byName);
System.out.println(products); // sorted alphabetically

reversed()

reversed() odwraca porządek dowolnego komparatora.

import java.util.Comparator;

Comparator<Product> mostExpensiveFirst =
    Comparator.comparingDouble(Product::price).reversed();

products.sort(mostExpensiveFirst);
System.out.println(products);
// [Laptop($999.0), Mouse($29.99), USB Hub($24.99)]

naturalOrder i reverseOrder

Comparator.naturalOrder() używa Comparable danej klasy. reverseOrder() odwraca ten porządek.

List<String> names = new ArrayList<>(List.of("Charlie", "Alice", "Bob"));

names.sort(Comparator.naturalOrder());
System.out.println(names); // [Alice, Bob, Charlie]

names.sort(Comparator.reverseOrder());
System.out.println(names); // [Charlie, Bob, Alice]

// Sort integers descending
List<Integer> nums = new ArrayList<>(List.of(5, 2, 8, 1, 9));
nums.sort(Comparator.reverseOrder());
System.out.println(nums); // [9, 8, 5, 2, 1]

Komparatory bezpieczne dla wartości null

Comparator.nullsFirst() i nullsLast() obsługują elementy null bez powodowania NPE.

import java.util.*;

List<String> withNulls = new ArrayList<>(Arrays.asList("Charlie", null, "Alice", null, "Bob"));

withNulls.sort(Comparator.nullsLast(Comparator.naturalOrder()));
System.out.println(withNulls); // [Alice, Bob, Charlie, null, null]

withNulls.sort(Comparator.nullsFirst(Comparator.naturalOrder()));
System.out.println(withNulls); // [null, null, Alice, Bob, Charlie]

sorted() w Stream z Comparator

Należy użyć pośredniej operacji strumienia sorted() wraz z Comparator do sortowania w stylu funkcyjnym.

import java.util.stream.*;

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

List<Employee> employees = List.of(
    new Employee("Alice",   "Engineering", 95000),
    new Employee("Bob",     "Marketing",   72000),
    new Employee("Charlie", "Engineering", 105000)
);

// Sort by salary descending in a stream pipeline
employees.stream()
    .sorted(Comparator.comparingDouble(Employee::salary).reversed())
    .forEach(e -> System.out.println(e.name() + ": $" + e.salary()));
// Charlie: $105000.0 / Alice: $95000.0 / Bob: $72000.0

Comparator jako lambda a odwołanie do metody

Odwołania do metod pozwalają jeszcze bardziej skrócić komparatory, gdy funkcja ekstrakcji klucza jest prostym getterem.

// Lambda
Comparator<String> c1 = (a, b) -> a.length() - b.length();

// Comparator.comparing with lambda
Comparator<String> c2 = Comparator.comparing(s -> s.length());

// Comparator.comparingInt with method reference (cleanest)
Comparator<String> c3 = Comparator.comparingInt(String::length);

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

Komparator ze stanem

Chociaż komparatory powinny zwykle być bezstanowe, można przekazywać im konfigurację za pomocą parametrów konstruktora.

class DistanceComparator implements Comparator<String> {
    private final String target;
    DistanceComparator(String target) { this.target = target; }

    @Override
    public int compare(String a, String b) {
        return Integer.compare(distance(a), distance(b));
    }

    private int distance(String s) { return Math.abs(s.length() - target.length()); }
}

List<String> words = new ArrayList<>(List.of("Java", "Go", "Python", "C", "Kotlin"));
words.sort(new DistanceComparator("Java"));
System.out.println(words); // closest length to "Java" first

Niestandardowe sortowanie katalogu produktów

Sortowanie katalogu produktów najpierw według dostępności, następnie ceny, a na końcu nazwy.

import java.util.*;

record Item(String name, double price, boolean inStock) {}

List<Item> catalog = List.of(
    new Item("Laptop",  999.0,  true),
    new Item("Case",     19.99, false),
    new Item("Mouse",    29.99, true),
    new Item("Monitor", 349.0,  true)
);

Comparator<Item> catalogSort =
    Comparator.comparing(Item::inStock).reversed()     // in-stock first
    .thenComparingDouble(Item::price)                  // then cheapest
    .thenComparing(Item::name);                        // then alphabetical

catalog.stream().sorted(catalogSort)
    .forEach(i -> System.out.printf("%s %-15s $%.2f%n",
        i.inStock() ? "[Y]" : "[N]", i.name(), i.price()));

Arrays.sort z Comparator

Arrays.sort(array, comparator) sortuje tablice obiektów za pomocą niestandardowego komparatora.

String[] words = {"banana", "fig", "apple", "kiwi", "cherry"};

// Sort by length, then alphabetically for same length
Arrays.sort(words,
    Comparator.comparingInt(String::length)
              .thenComparing(Comparator.naturalOrder()));

System.out.println(Arrays.toString(words));
// [fig, kiwi, apple, banana, cherry]

Szybkie sprawdzenie

Co zwraca Comparator.comparingDouble(Product::price).reversed()?

Podsumowanie: Comparator i sortowanie za pomocą lambd

Najważniejsze informacje:

  • Comparator<T> definiuje zewnętrzny porządek — można używać dowolnej liczby komparatorów
  • Comparator.comparing(keyExtractor) tworzy komparatory na podstawie getterów
  • reversed() odwraca dowolny komparator; naturalOrder()/reverseOrder() służą do typów implementujących Comparable
  • nullsFirst() i nullsLast() bezpiecznie obsługują elementy null
  • W potokach Stream należy używać sorted(comparator) do porządkowania w stylu funkcyjnym
  • Komparatory można przekazywać do sort(), Arrays.sort(), TreeSet i TreeMap

Często zadawane pytania

Czy lekcja „Comparator i sortowanie za pomocą lambd” jest bezpłatna?

Tak — pełny tekst „Comparator i sortowanie za pomocą lambd” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Comparator i sortowanie za pomocą lambd”?

Twórz obiekty Comparator za pomocą wyrażeń lambda i fabrycznych metod Comparator.comparing. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 2 z 4.

Ile czasu zajmuje lekcja „Comparator i sortowanie za pomocą lambd”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Interfejs Comparable
  2. Comparator i sortowanie za pomocą lambd
  3. Sortowanie według wielu kluczy za pomocą thenComparing
  4. Sortowanie tablic i kolekcji w praktyce
← Powrót do Java Academy