Java Academy · Lektion

Egen ordning i trädstrukturerade samlingar

Skicka in en Comparator till TreeMap/TreeSet för att definiera domänspecifika sorteringsordningar.

Lektion 4 av 413 steg

Egen ordning i trädstrukturerade samlingar är en gratis lektion i Java Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Java Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Java Academy innehåller totalt 4 lektioner.

Varför anpassad ordning?

Trädliknande samlingar (TreeMap, TreeSet) använder som standard naturlig ordning. När domänobjekten saknar en naturlig ordning, eller när Ni behöver en annan sortering, anger Ni en Comparator när samlingen skapas.

Comparator när TreeMap skapas

Skicka med en comparator för att sortera nycklar enligt en anpassad regel – till exempel i omvänd alfabetisk ordning:

import java.util.*;

TreeMap<String, Integer> map = new TreeMap<>(Comparator.reverseOrder());
map.put("banana", 2);
map.put("apple", 1);
map.put("cherry", 3);

map.forEach((k,v) -> System.out.println(k)); // cherry, banana, apple

Comparator när TreeSet skapas

Ange en comparator till TreeSet för att styra sorteringsordningen oberoende av elementens naturliga ordning:

TreeSet<String> byLength = new TreeSet<>(
    Comparator.comparingInt(String::length)
              .thenComparing(Comparator.naturalOrder())
);
byLength.addAll(List.of("fig","apple","kiwi","date","banana"));

for (String s : byLength) System.out.print(s + " ");
// fig date kiwi apple banana

Sortera objekt efter flera fält

Kedja comparators för att sortera efter ett primärt fält och sedan efter ett sekundärt fält som skiljer lika värden åt:

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

TreeSet<Employee> sorted = new TreeSet<>(
    Comparator.comparing(Employee::dept)
              .thenComparingInt(Employee::salary).reversed()
              .thenComparing(Employee::name)
);
sorted.add(new Employee("Alice", "Eng", 90_000));
sorted.add(new Employee("Bob",   "Eng", 85_000));
sorted.add(new Employee("Carol", "HR",  70_000));

for (Employee e : sorted) System.out.println(e.dept()+" "+e.name());

Överensstämmelse med equals

Kritisk regel: den comparator som används av TreeSet/TreeMap definierar likhet för samlingen. Om comparator.compare(a, b) == 0 betraktas både a och b som samma nyckel – även om a.equals(b) är false.

// Comparator ignoring case — "apple" and "APPLE" become the same key!
TreeSet<String> ci = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
ci.add("apple");
ci.add("APPLE"); // not added — same by comparator
System.out.println(ci.size()); // 1

Skiftlägesokänslig TreeMap

Ett vanligt praktiskt behov är en TreeMap där nycklarna är skiftlägesokänsliga strängar, vilket är användbart för HTTP-huvuden och konfigurationsnycklar:

TreeMap<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
headers.put("Content-Type", "application/json");
headers.put("content-type", "text/html"); // overwrites!

System.out.println(headers.get("CONTENT-TYPE")); // text/html
System.out.println(headers.size()); // 1

Nullsäker comparator

Trädliknande samlingar med naturlig ordning kastar NPE för null-nycklar. Använd en nullsäker comparator för att tillåta null som den minsta nyckeln:

TreeMap<String, Integer> map = new TreeMap<>(
    Comparator.nullsFirst(Comparator.naturalOrder())
);
map.put(null, 0);
map.put("b", 2);
map.put("a", 1);

map.forEach((k,v) -> System.out.println(k + "=" + v));
// null=0, a=1, b=2

Exempel på domänobjekt: produkt efter pris

Sortera produkter efter pris i en TreeSet och använd namnet som skiljande faktor för att bevara unika element:

record Product(String name, double price) {}

TreeSet<Product> catalog = new TreeSet<>(
    Comparator.comparingDouble(Product::price)
              .thenComparing(Product::name)
);
catalog.add(new Product("Widget", 9.99));
catalog.add(new Product("Gadget", 24.99));
catalog.add(new Product("Donut",  9.99));

catalog.forEach(p -> System.out.println(p.name() + " $" + p.price()));
// Donut $9.99, Widget $9.99, Gadget $24.99

Hämta comparatorn

Anropa comparator() på en TreeMap/TreeSet för att hämta den anpassade comparatorn. Returnerar null om naturlig ordning används.

TreeMap<String, Integer> map = new TreeMap<>(Comparator.reverseOrder());
System.out.println(map.comparator() != null); // true

TreeMap<String, Integer> natural = new TreeMap<>();
System.out.println(natural.comparator());      // null

Sammansättning av comparators

Javas Comparator erbjuder kedjbara fabriksmetoder för en tydlig sammansättning:

Comparator<String> comp =
    Comparator.comparingInt(String::length)   // by length
              .thenComparing(Comparator.naturalOrder()); // then alphabetically

TreeSet<String> ts = new TreeSet<>(comp);
ts.addAll(List.of("go", "java", "c", "rust", "py"));
ts.forEach(s -> System.out.print(s + " "));
// c go py java rust

När Ni INTE bör använda en anpassad comparator

Undvik att använda en comparator som inte överensstämmer med equals för TreeMap-nycklar eller TreeSet-element – det leder till förvirrande poster som verkar saknas. Säkerställ att compare(a, b) == 0 gäller om och endast om a.equals(b) gäller, så att samlingen fungerar korrekt i alla sammanhang.

Snabb kontroll

En TreeSet använder endast en comparator baserad på String::length. Vad händer när Ni lägger till både "cat" och "dog"?

Sammanfattning: Anpassad ordning

Viktiga punkter:

  • Skicka en Comparator till TreeMap- eller TreeSet-konstruktorn för att definiera en anpassad ordning
  • Jämlikhet enligt Comparator styr unikheten i träd-baserade samlingar
  • Se till att Comparator är konsekvent med equals för att undvika överraskningar
  • Använd Comparator.nullsFirst/nullsLast för null-säker sortering
  • Kedja med thenComparing för sortering på flera fält
Gratis att börja

Lär dig Java med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
104
Lektioner
374

Vanliga frågor

Är lektionen ”Egen ordning i trädstrukturerade samlingar” gratis?

Ja – hela texten till ”Egen ordning i trädstrukturerade samlingar” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Java Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Java Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Egen ordning i trädstrukturerade samlingar”?

Skicka in en Comparator till TreeMap/TreeSet för att definiera domänspecifika sorteringsordningar. Ni övar på Java Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Java Academy?

Du behöver inga förkunskaper. Utbildningen i Java Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Egen ordning i trädstrukturerade samlingar”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Java Academy-lektionen?

Ja. Varje Java Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. TreeMap: sorterade nyckel-värde-par
  2. Delkartor och intervallvyer
  3. TreeSet och NavigableSet
  4. Egen ordning i trädstrukturerade samlingar
← Tillbaka till Java Academy