HashMaps en collecties in Java

Leer gegevens met HashMap op sleutel op te slaan en op te zoeken, waarden te tellen en te groeperen en met HashSet unieke waarden te bewaren. Bekijk welke garanties de interfaces List, Set en Map bieden, sorteer lijsten en geef je eigen klassen een natuurlijke volgorde met Comparable. Kies de collectie die bij elke taak past.

BeginnerLes 7 van 11 in Cursus Java programmeren: klassen, overerving, collecties en streams

Wat je leert

  1. Maak hashmaps, voeg sleutel-waardeparen toe, lees, wijzig en verwijder ze, doorloop de inhoud van een map en gebruik je eigen klassen als sleutels die de map kan terugvinden.
    • Maak een HashMap en voeg sleutel-waardeparen toe, vraag die op, werk die bij en verwijder die
      Declareer een HashMap met de sleutel- en waardetypen, sla paren op met put, lees ze met get en handel ontbrekende sleutels af.
    • Doorloop sleutels, waarden en sleutel-waardeparen
      Doorloop elk paar in een map met keySet, values en entrySet, weet welke volgorde je kunt verwachten en wijzig een map veilig tijdens het doorlopen.
    • Gebruik je eigen objecten als sleutels in een map
      Maak objecten van je eigen klassen bruikbaar als sleutels door equals en hashCode samen te overschrijven en laat sleutels ongewijzigd zolang ze in een map staan.
  2. Gebruik maps om te tellen hoe vaak waarden voorkomen, verwante waarden onder één sleutel te verzamelen en opzoektabellen te maken waarmee je objecten snel vindt.
    • Tel hoe vaak waarden voorkomen en bereken totalen per sleutel
      Maak frequentietabellen en lopende totalen met het getOrDefault-patroon en lees de resultaten correct.
    • Groepeer waarden onder één sleutel met lijsten en verzamelingen als mapwaarden
      Maak maps waarvan de waarden lijsten of verzamelingen zijn, voeg elementen toe aan de juiste groep en voorkom fouten waardoor groepen verloren gaan of onbruikbaar worden.
    • Zoek objecten en prijzen snel op met een index op basis van een map
      Gebruik maps als opzoektabellen en indexen die objecten via een unieke sleutel vinden, bewaar ze binnen een klasse en houd meerdere indexen consistent.
  3. Gebruik HashSet om waarden zonder duplicaten op te slaan, lidmaatschap snel te testen en verzamelingen te combineren met vereniging, doorsnede en verschil.
    • Sla unieke waarden op en test lidmaatschap met HashSet
      Voeg waarden toe aan een HashSet, controleer en verwijder ze, gebruik het resultaat van add en verwijder duplicaten uit een lijst.
    • Combineer verzamelingen en behoud hun volgorde
      Bereken verenigingen, doorsneden en verschillen zonder de oorspronkelijke verzamelingen te wijzigen, vergelijk verzamelingen en kies een geordende verzameling als de volgorde ertoe doet.
  4. Declareer collecties met hun interfacetypen, weet welke garanties elke interface biedt en gebruik de gemeenschappelijke methoden die bij verschillende implementaties werken.
    • Declareer variabelen en parameters met interfacetypen
      Leg uit wat een interfacetype is, declareer collecties als List, Set of Map en schrijf methoden die elke implementatie accepteren.
    • Weet welke garanties List, Set en Map bieden
      Vergelijk de garanties van de drie interfaces, herken hun belangrijkste implementaties en werk met niet-wijzigbare collecties die met of zijn gemaakt.
  5. Sorteer lijsten in natuurlijke volgorde, geef je eigen klassen een natuurlijke volgorde door Comparable te implementeren en gebruik die volgorde in gesorteerde verzamelingen en maps.
    • Sorteer lijsten met getallen en strings
      Sorteer een lijst ter plaatse met Collections.sort, voorspel de volgorde van strings en sorteer in omgekeerde volgorde of zonder onderscheid tussen hoofdletters en kleine letters.
    • Implementeer Comparable in je eigen klasse
      Geef een klasse een natuurlijke volgorde door Comparable te implementeren en compareTo te schrijven met veilige vergelijkingen van getallen en strings.
    • Gebruik aanvullende sorteercriteria en werk met gesorteerde verzamelingen en maps
      Orden objecten op meerdere velden, houd compareTo consistent met equals en gebruik TreeSet en TreeMap om gegevens gesorteerd te houden.
  6. Vergelijk hoe snel veelgebruikte bewerkingen in elke collectie zijn en kies het type dat past bij wat het programma met zijn gegevens moet doen.
    • Vergelijk de kosten van veelgebruikte collectiebewerkingen
      Schat hoe de tijd voor opzoeken, toevoegen en verwijderen groeit met de grootte van elke collectie en herken trage patronen.
    • Kies een collectie die bij de taak past
      Beantwoord enkele vragen over volgorde, duplicaten en opzoeken om te kiezen tussen arrays, lijsten, verzamelingen en maps en combineer ze voor complexere gegevens.

HashMaps en collecties in Java: uitleg

6 hoofdstukken

1

Sla gegevens op en zoek die op via een sleutel met HashMap

Een productcode kan rechtstreeks naar een voorraadhoeveelheid leiden, zonder een lijst te doorzoeken. Maps maken die koppeling expliciet. Om ze goed te gebruiken, moet je ook ontbrekende sleutels afhandelen, paren veilig doorlopen en definiëren wanneer twee sleutelobjecten als gelijk gelden. Begin met een kleine voorraadmap en volg hoe de inhoud verandert en hoe Java een opgeslagen sleutel terugvindt. Dezelfde gelijkheidsregels zijn van belang wanneer je verzamelingen gebruikt.

1.1 Maak een HashMap en voeg sleutel-waardeparen toe, vraag die op, werk die bij en verwijder die

Een map bewaart een koppeling van elke sleutel naar één waarde. In een voorraadmap is een productnaam de sleutel en de hoeveelheid de waarde. Twee producten kunnen dezelfde hoeveelheid hebben, maar één productsleutel kan niet twee afzonderlijke sleutel-waardeparen hebben.

Maak de map
import java.util.HashMap;

HashMap<String, Integer> stock = new HashMap<>();

Het eerste type, String, beschrijft sleutels. Het tweede, Integer, beschrijft waarden. Met de diamantnotatie <> rechts kan Java die typen afleiden. Typeargumenten moeten referentietypen zijn: gebruik Integer, Double, Character of Boolean in plaats van int, double, char of boolean. Java zet een gewone int via autoboxing om als die als Integer wordt opgeslagen en zet een Integer via unboxing om als een int nodig is.

Volg elke wijziging
stock.put("apple", 12);
stock.put("pear", 7);
Integer previous = stock.put("apple", 15);

De eerste aanroep maakt apple=12; de tweede voegt pear=7 toe. De derde vindt de bestaande sleutel "apple" en vervangt de waarde ervan. De map heeft nu twee sleutel-waardeparen en previous bevat 12. Een put voor een sleutel die nog niet aan een waarde is gekoppeld, geeft null terug.

stock.get("apple") geeft nu 15 terug. stock.remove("pear") geeft 7 terug en verwijdert dat paar. Als je "pear" opnieuw verwijdert, krijg je null terug. size() telt de paren, isEmpty() controleert of er geen paren zijn en clear() verwijdert alle paren.

Handel een ontbrekende sleutel af

stock.get("kiwi") geeft null terug en stock.containsKey("kiwi") geeft false terug. Deze instructie compileert, maar mislukt tijdens de uitvoering:

int quantity = stock.get("kiwi");

Java probeert null via unboxing om te zetten naar een int, waardoor een NullPointerException ontstaat. Gebruik bij een map met hoeveelheden die niet null zijn een standaardwaarde:

int quantity = stock.getOrDefault("kiwi", 0);

Dit geeft 0 zonder "kiwi" aan de map toe te voegen. Je kunt ook containsKey controleren voordat je leest. containsValue(15) vraagt of een van de paren die waarde heeft; de methode kan alle waarden doorzoeken en verschilt dus van het zoeken naar een bekende sleutel.

Een HashMap staat ook een null-sleutel en null-waarden toe. Als een sleutel expliciet aan null is gekoppeld, geeft getOrDefault die opgeslagen null terug, niet de standaardwaarde. Met containsKey onderscheid je dat geval van een ontbrekende sleutel. Voorraadmaps zijn eenvoudiger als elke opgeslagen hoeveelheid een echt getal is.

Vergelijk sleutels en waarden correct

Strings als sleutel zijn hoofdlettergevoelig: "apple", "Apple" en "apple " zijn verschillend. Pas vóór het opslaan en zoeken dezelfde opschoning toe, zoals name.trim().toLowerCase(). Alleen een zoeksleutel opschonen kan inconsistent opgeslagen sleutels niet herstellen.

Vergelijk waarden in wrapperobjecten op inhoud met equals. Als twee paren elk 1000 bevatten, kunnen hun Integer-referenties verschillen, zodat == onwaar kan zijn hoewel hun numerieke inhoud overeenkomt. Nadat je hebt gecontroleerd dat beide waarden niet null zijn, vergelijkt a.equals(b) hun inhoud.

Belangrijkste punten

  • Elke unieke sleutel is aan één waarde gekoppeld; waarden mogen vaker voorkomen.
  • put vervangt een bestaande waarde en geeft de vorige waarde terug.
  • Een get voor een ontbrekende sleutel geeft null terug; unboxing daarvan veroorzaakt een NullPointerException.
  • getOrDefault geeft alleen een standaardwaarde voor een ontbrekende sleutel.
  • Vergelijk strings als sleutel consequent en vergelijk waarden in wrapperobjecten op inhoud.

1.2 Doorloop sleutels, waarden en sleutel-waardeparen

Een map kan één zoekactie beantwoorden of al zijn gegevens aan een lus aanbieden. Kies de weergave die de onderdelen geeft die de lus nodig heeft. De weergaven zijn gekoppeld aan de map, dus wijzigingen via die weergaven kunnen ook de map wijzigen.

Kies sleutels, waarden of sleutel-waardeparen

Gebruik keySet() om sleutels te doorlopen. Met een zoekactie binnen die lus kun je elke waarde ophalen:

for (String name : phoneBook.keySet()) {
    System.out.println(name + ": " + phoneBook.get(name));
}

Gebruik values() als de sleutels niet relevant zijn. Voor de voorraadhoeveelheden appel 15, peer 7 en vijg 3:

int total = 0;
for (int quantity : stock.values()) {
    total += quantity;
}

Het totaal wordt 25. Herhaalde waarden leveren nog steeds afzonderlijke bijdragen: een waardenweergave is geen verzameling.

Een sleutel-waardepaar bevat een sleutel en de bijbehorende waarde samen. Importeer java.util.Map en gebruik Map.Entry<K, V> met getKey() en getValue(). Zo voorkom je een tweede zoekactie:

String best = null;
int bestScore = Integer.MIN_VALUE;
for (Map.Entry<String, Integer> entry : scores.entrySet()) {
    if (best == null || entry.getValue() > bestScore) {
        best = entry.getKey();
        bestScore = entry.getValue();
    }
}

Voor Ana 82, Ben 91 en Cai 77 is het resultaat Ben met 91. De test best == null handelt ook een eerste score af die gelijk is aan de kleinst mogelijke int. Bij een lege map blijft best gelijk aan null.

Kies de volgorde expliciet

Een HashMap garandeert geen iteratievolgorde. Je kunt niet uitgaan van invoegvolgorde, gesorteerde volgorde of de volgorde waarin de map vandaag wordt weergegeven. Een LinkedHashMap behoudt de invoegvolgorde; een TreeMap doorloopt gesorteerde sleutels. Als twee scores gelijk zijn, bewaart de lus hierboven de eerste die wordt aangetroffen. Bij een HashMap kan elk van de namen met de hoogste score winnen. Voeg een expliciete regel voor een gelijke stand toe als het resultaat voorspelbaar moet zijn.

Verwijder paren via de iterator

Als je stock.remove(key) aanroept binnen een for-each-lus over stock.keySet(), verander je de sleutels die de lus doorloopt. Dit kan een ConcurrentModificationException veroorzaken. Detectie is niet gegarandeerd; een uitvoering zonder exceptie maakt dit patroon niet geldig.

Gebruik de eigen verwijdermethode van de iterator:

Iterator<Map.Entry<String, Integer>> it =
    stock.entrySet().iterator();
while (it.hasNext()) {
    if (it.next().getValue() == 0) {
        it.remove();
    }
}

Importeer java.util.Iterator. Voor appel 15, peer 0, vijg 0 en kiwi 4 verwijdert dit peer en vijg. Een andere veilige aanpak is om sleutels in een lijst te bewaren, de lus af te maken en die sleutels daarna te verwijderen.

Een bestaande waarde vervangen voegt geen sleutel toe en verwijdert er geen. Tijdens een lus over sleutel-waardeparen kan entry.setValue(entry.getValue() * 2) de hoeveelheden veilig verdubbelen. Voeg tijdens die lus geen nieuwe sleutels toe via de map.

Onderscheid een weergave van een kopie

stock.keySet().remove("apple") verwijdert het bijbehorende sleutel-waardepaar uit de map. Een aparte lijst die je maakt met new ArrayList<>(stock.keySet()) is een kopie van de huidige sleutels. Het sorteren van die lijst verandert de volgorde van de map niet en het verwijderen van een naam uit de lijst verwijdert de bijbehorende koppeling niet.

Belangrijkste punten

  • Gebruik keySet, values of entrySet afhankelijk van wat de lus nodig heeft.
  • HashMap heeft geen gegarandeerde iteratievolgorde; bepaal expliciet wat bij een gelijke stand gebeurt.
  • Gebruik de remove-methode van een iterator om tijdens het doorlopen te verwijderen.
  • Een bestaande waarde vervangen is toegestaan tijdens het doorlopen.
  • Mapweergaven zijn gekoppeld aan de map; een gekopieerde lijst met sleutels staat er los van.

1.3 Gebruik je eigen objecten als sleutels in een map

Een product-ID die als String is opgeslagen, heeft al bruikbare gelijkheidsregels. Bij een sleutel van je eigen klasse moet je een keuze maken: stellen twee afzonderlijke objecten met dezelfde gegevens dezelfde sleutel voor?

Hashcodes beperken de zoekactie; gelijkheid bevestigt de overeenkomst

Een HashMap gebruikt hashCode() om een sleutel te helpen lokaliseren en equals() om een overeenkomst te controleren. Gelijke sleutels moeten gelijke hashcodes hebben. Verschillende sleutels kunnen een hashcode delen; gelijkheid onderscheidt ze nog steeds. Standaardwaardeklassen zoals String en Integer volgen dit contract al.

Zonder overschrijvingen erft een klasse van Object gelijkheid op basis van identiteit. Twee afzonderlijk gemaakte punten met coördinaten 2 en 3 zijn verschillende sleutels, ook al komen hun velden overeen:

labels.put(new Point(2, 3), "door");
String label = labels.get(new Point(2, 3));

Bij gelijkheid op basis van identiteit is label gelijk aan null. De zoekactie maakte een tweede object, niet het object dat voor het toevoegen is gebruikt.

Overschrijf het paar samen

Hier bepaalt een punt zijn inhoud via de coördinaten:

import java.util.Objects;

final class Point {
    private final int x;
    private final int y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof Point)) {
            return false;
        }
        Point point = (Point) other;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

De identiteitscontrole handelt hetzelfde object snel af. De typecontrole wijst null en objecten van een niet-verwant type af. De laatste vergelijking controleert beide coördinaten. Objects.hash(x, y) bouwt de hashcode op uit diezelfde velden. Met deze klasse geeft de zoekactie hierboven "door" terug.

Als je alleen equals overschrijft, blijft de overgeërfde hashcodebepaling bestaan. Die garandeert geen gelijke hashcodes voor afzonderlijke objecten met gelijke velden. Een map kan daardoor een gelijke sleutel missen. Een constante hashcode zou de juistheid behouden, maar het zoeken vertragen. Als je beide overschrijvingen in een editor genereert, voorkom je makkelijker dat de gebruikte velden niet overeenkomen.

Gebruik de exacte methodesignatuur

public boolean equals(Point other) overlaadt de methode; die vervangt equals(Object) niet. Bij het opzoeken in een map wordt equals(Object) gebruikt, dus geeft de nieuwe overladen methode de map geen inhoudelijke gelijkheid. De annotatie @Override maakt van een verkeerde signatuur een compilatiefout in plaats van een verborgen fout bij het opzoeken.

Houd de identiteit van een sleutel stabiel

Wijzig velden die de gelijkheid of hashcode van een sleutel bepalen niet zolang de sleutel is opgeslagen. Als een opgeslagen punt verandert van (2, 3) naar (5, 3), kan de map het onder geen van beide waarden meer vinden, ook al is size() ongewijzigd. Verwijder het punt voordat je het wijzigt en voeg het daarna opnieuw toe. Door sleutelvelden final te maken, zoals hierboven, voorkom je deze fout.

Deze regels bepalen ook het lidmaatschap van een HashSet. Een ArrayList gebruikt equals voor zoekacties op inhoud zoals contains; voor die zoekactie zijn geen hashcodes nodig.

Belangrijkste punten

  • Gelijke objecten moeten gelijke hashcodes hebben; ongelijke objecten mogen een hashcode delen.
  • Overschrijf equals(Object) en hashCode() met dezelfde velden.
  • @Override ontdekt een onbedoeld overladen equals-methode.
  • Laat velden die gelijkheid en hashcode bepalen ongewijzigd zolang een sleutel is opgeslagen.
2

Tel, groepeer en indexeer gegevens met maps

Een map kan bruikbare informatie opbouwen terwijl een programma gegevens leest: een aantal voor elk woord, een lijst voor elke cursus of een object voor elke ID. De belangrijke keuze is wat één waarde voorstelt. Een getal bouwt een resultaat op; een lijst of verzameling brengt een groep bijeen; een objectreferentie vormt een index. Volg elke bijwerking vanaf een lege map, zodat duidelijk is wat er gebeurt bij eerste voorkomens, herhaalde sleutels en gedeelde objecten.

2.1 Tel hoe vaak waarden voorkomen en bereken totalen per sleutel

Een frequentietabel heeft één sleutel voor elk uniek element en een getal dat aangeeft hoe vaak het voorkomt. Het eerste voorkomen begint een telling; elk volgend voorkomen werkt hetzelfde sleutel-waardepaar bij.

Bouw een telling element voor element op
HashMap<String, Integer> counts = new HashMap<>();
for (String word : text.split(" ")) {
    int oldCount = counts.getOrDefault(word, 0);
    counts.put(word, oldCount + 1);
}

Voor een tekst waarin "the" als eerste woord voorkomt, ontbreekt die sleutel aanvankelijk, dus is het oude aantal 0 en het nieuwe aantal 1. De volgende twee keren dat het woord voorkomt, verandert het aantal in dat paar naar 2 en daarna 3. "cat" eindigt op 2; "saw", "dog", "and" en "ran" eindigen elk op 1.

Er zijn 6 unieke woorden, dus is counts.size() gelijk aan 6. De waarden tellen op tot 9, het aantal voorkomens van woorden. Dit zijn verschillende maten: de grootte van de map is niet de lengte van de oorspronkelijke reeks.

De bijwerking kan op één regel worden geschreven:

counts.put(word, counts.getOrDefault(word, 0) + 1);

Een gelijkwaardige langere vorm controleert containsKey, verhoogt een bestaand aantal en slaat 1 op voor een nieuwe sleutel. Alle aantallen die met dit patroon worden opgeslagen, zijn niet null.

Behoud het oude resultaat

Als je voor elk woord counts.put(word, 1) aanroept, overschrijf je elk aantal steeds opnieuw met 1. Zo leg je vast dat een woord bestaat, maar gaat de frequentie verloren. Als je counts.get(word) + 1 aanroept zonder het eerste voorkomen af te handelen, probeert Java null via unboxing om te zetten en mislukt de uitvoering. De standaardwaarde hoort bij het lezen; het verhoogde aantal moet daarna worden teruggeplaatst.

Bepaal wat als hetzelfde element telt

Gelijkheid van strings is exact. "The" en "the" zijn verschillende sleutels, net als "cat" en "cat,". Als de taak die als hetzelfde woord beschouwt, schoon dan elk token op voordat je het telt. Zet tekst om naar kleine letters en verwijder de leestekens die het programma als scheidingstekens behandelt. Gebruik één consistente regel zodat de resultaten niet afhangen van welke schrijfwijze het eerst voorkwam.

De sleutel kan ook een teken zijn. Met HashMap<Character, Integer> levert een lus over "banana".toCharArray() met hetzelfde patroon van lezen, verhogen en opslaan a=3, n=2 en b=1 op.

Tel bedragen op in plaats van voorkomens

Tel voor categorietotalen het huidige bedrag op in plaats van 1:

HashMap<String, Double> totals = new HashMap<>();
double oldTotal = totals.getOrDefault(category, 0.0);
totals.put(category, oldTotal + amount);

Eten 12,50, vervoer 3,20 en eten 7,25 leveren eten 19,75 en vervoer 3,20 op. De standaardwaarde is 0.0, passend bij het waardetype Double. De map heeft nog steeds één paar per categorie, ongeacht hoeveel bedragen hebben bijgedragen.

Lees de voltooide tabel

Doorloop sleutel-waardeparen om het grootste aantal of totaal te vinden en onthoud daarbij de beste sleutel en waarde. Leg zo nodig een regel voor gelijke standen vast. Voor een alfabetisch overzicht kopieert new TreeMap<>(counts) de koppelingen in gesorteerde sleutelvolgorde. De aantallen blijven ongewijzigd; de sleutels sorteren sorteert de categorieën niet op hun totalen.

Belangrijkste punten

  • Een frequentieregistratie in een map bewaart één aantal per unieke sleutel.
  • Lees het oude aantal met nul als standaardwaarde, tel er één bij op en sla het resultaat op.
  • De mapgrootte telt unieke elementen; de som van de aantallen meet het aantal voorkomens.
  • Normaliseer tekst consequent voordat je telt.
  • Gebruik hetzelfde bijwerkpatroon om bedragen per sleutel op te tellen.
  • Kies de volgorde van het overzicht los van de opgetelde waarden.

2.2 Groepeer waarden onder één sleutel met lijsten en verzamelingen als mapwaarden

Een mapwaarde kan een collectie zijn. Als meerdere studenten bij één cursus horen, is de cursus een sleutel en bevat de bijbehorende lijst alle studenten van die cursus. De regel dat maps unieke sleutels hebben, geldt nog steeds: de lijst is de ene waarde voor die cursus.

Maak een groep voordat je er iets aan toevoegt
HashMap<Character, ArrayList<String>> groups = new HashMap<>();
for (String fruit : fruits) {
    char letter = fruit.charAt(0);
    if (!groups.containsKey(letter)) {
        groups.put(letter, new ArrayList<>());
    }
    groups.get(letter).add(fruit);
}

Voor “appel”, “banaan”, “avocado”, “kers” en “bes” maakt de eerste vrucht de lijst voor a en voegt “appel” toe. “Banaan” maakt de lijst voor b. “Avocado” vindt de bestaande lijst voor a en voegt zichzelf achteraan toe. Het resultaat is a → [appel, avocado], b → [banaan, bes] en k → [kers]. Elke lijst behoudt zijn eigen invoegvolgorde, ook al ordent de HashMap zijn sleutels niet.

De controle kan korter:

groups.putIfAbsent(letter, new ArrayList<>());
groups.get(letter).add(fruit);

putIfAbsent behoudt een bestaande lijst die niet null is. De daaropvolgende get geeft die lijst terug, klaar voor de toevoeging.

Behoud de lijst die je al hebt opgebouwd

Een onvoorwaardelijke groups.put(letter, new ArrayList<>()) binnen de lus vervangt bij elk voorkomen de oude lijst. Na de volgende add blijft alleen de laatste vrucht per letter over. De tegenovergestelde fout is het aanmaken helemaal overslaan: groups.get(letter).add(fruit) werpt voor een nieuwe sleutel een NullPointerException op omdat er nog geen lijst bestaat.

Begrijp de referentie

get geeft de opgeslagen lijstreferentie terug. Als je daar iets aan toevoegt, verandert diezelfde lijst, dus hoef je die niet terug te plaatsen. Dit verklaart ook een fout met gedeelde referenties:

ArrayList<String> shared = new ArrayList<>();
courses.put("Art", shared);
courses.put("Music", shared);
courses.get("Art").add("Jin");

Beide sleutels leiden nu naar [Jin]. Twee sleutels hebben niet twee lijsten gemaakt. Maak voor elke nieuwe groep een nieuwe lijst als de groepen onafhankelijk moeten zijn.

Kies lijsten of verzamelingen binnen groepen

Een lijst behoudt herhaalde toevoegingen. Een verzameling voorkomt duplicaten binnen die groep. Een HashMap<String, HashSet<String>> kan zo de verschillende cursuslidmaatschappen van elke student verzamelen zonder dezelfde student twee keer in één cursus te tellen. De verzamelingsregel geldt binnen elke waarde; de buitenste map heeft nog steeds één paar per cursus.

Controleer bij het lezen van een groep die mogelijk ontbreekt containsKey of gebruik groups.getOrDefault(letter, new ArrayList<>()). Een ontbrekende sleutel levert dan voor die aanroep een lege lijst op. De standaardlijst wordt niet automatisch ingevoegd; als je er iets aan toevoegt, ontstaat geen opgeslagen groep.

Als je het laatste element van een groep verwijdert, blijft de sleutel aan een lege collectie gekoppeld. Als het programma lege groepen niet langer moet vermelden, controleer dan isEmpty() en verwijder ook die sleutel. Tel groepen met de grootte van de buitenste map en elementen met de groottes van de binnenste collecties.

Belangrijkste punten

  • Zorg dat een groep bestaat en voeg daarna iets toe aan de opgeslagen lijst of verzameling.
  • Maak voor elke onafhankelijke groep een nieuwe collectie.
  • get geeft de opgeslagen referentie terug, dus wijzigingen binnen de collectie vereisen geen extra put.
  • Lijsten als waarde behouden herhalingen; verzamelingen als waarde bewaren unieke groepsleden.
  • Een opgeslagen lege groep heeft nog steeds een sleutel-waardepaar in de map.

2.3 Zoek objecten en prijzen snel op met een index op basis van een map

Een index koppelt een identificerende sleutel aan een object. Een bibliotheek kan een boek via het ISBN vinden zonder elk boek in een lijst te doorzoeken. Een opzoektabel gebruikt dezelfde vorm om een code aan een eenvoudige waarde te koppelen, zoals een productprijs.

Kies een identificerende sleutel

Een HashMap<String, Book> kan een ISBN aan het bijbehorende boek koppelen. Elke zoekactie heeft alleen de sleutel nodig. De naam van een persoon is vaak geen goede unieke sleutel: als je een andere persoon met de naam “Sam Lee” onder dezelfde string opslaat, vervangt die de vorige persoon. Gebruik een unieke ID of gebruik een groepeermap als één naam naar meerdere personen moet leiden.

Bewaar een index binnen de klasse die verantwoordelijk is voor de gegevens:

class Library {
    private HashMap<String, Book> byIsbn;

    Library() {
        byIsbn = new HashMap<>();
    }

    void addBook(Book book) {
        byIsbn.put(book.getIsbn(), book);
    }

    Book findByIsbn(String isbn) {
        return byIsbn.get(isbn);
    }
}

Hier biedt Book een methode getIsbn() aan. Aanroepers gebruiken addBook en findByIsbn; ze hoeven niet te weten welke mapimplementatie is opgeslagen. Het privéveld geeft de klasse ook één plek om haar regels voor het toevoegen en vervangen van boeken te onderhouden.

Controleer een ontbrekend resultaat

Als findByIsbn de waarde null teruggeeft, is geen boek gevonden. Test het resultaat voordat je er een methode op aanroept:

Book found = library.findByIsbn("978-0-00-000000-2");
if (found != null) {
    found.setOnLoan(true);
}

Als je setOnLoan rechtstreeks op een ontbrekend resultaat aanroept, wordt een NullPointerException opgeworpen. Een methode zoals hasBook(isbn) is een andere manier om aanroepers op een sleutel te laten controleren.

Volg gedeelde objecten door indexen heen

Een map slaat een objectreferentie op, geen nieuwe kopie van dat object. Als hetzelfde boek in een lijst met alle boeken, een ISBN-map en een groepering op auteur staat, wijzigt setOnLoan(true) het ene boek waarnaar alle drie verwijzen. Zo voorkom je dat drie afzonderlijke boekobjecten uiteen gaan lopen.

De collectiestructuren zelf moeten nog steeds worden onderhouden. Als je een boek uit de ISBN-map verwijdert, verwijder je de referentie niet uit de lijst van een auteur. Als een bibliotheek beide indexen bijhoudt, moeten de methoden voor toevoegen en verwijderen beide bijwerken. Door die wijzigingen te centraliseren in methoden zoals addBook en removeBook blijven zoekacties consistent.

Gebruik een tabel in een berekening

Stel dat een prijstabel koffie 2,50, thee 2,00 en muffin 3,25 bevat. Voor twee koffie en één muffin:

double cost = 2 * prices.get("coffee") + prices.get("muffin");

Het subtotaal voor de koffie is 5,00; daar 3,25 bij optellen geeft 8,25. De sleutels identificeren producten en de waarden leveren de bedragen. Voor een ontbrekend product moet je vóór de berekening een expliciete keuze maken: een standaardwaarde nul zou het product ongemerkt als gratis behandelen. Dezelfde opzoektechniek kan dus een andere regel voor ontbrekende sleutels nodig hebben dan een frequentietabel.

Belangrijkste punten

  • Een index vindt objecten via een identificerende sleutel.
  • Gebruik een unieke sleutel of groepeer meerdere overeenkomende objecten expliciet.
  • Indexen delen objectreferenties, maar toevoegingen en verwijderingen moeten elke index bijwerken.
  • Houd maps met gegevens privé en bied methoden aan die hun regels handhaven.
3

Bewaar unieke waarden in verzamelingen

Soms is de vraag eenvoudigweg of een waarde al eerder is voorgekomen. Verzamelingen passen direct bij die vraag en kunnen ook groepen waarden vergelijken, zoals mensen die twee evenementen bezoeken. Doordat ze geen dubbele elementen bevatten, veranderen zowel de code die je schrijft als de betekenis van de uiteindelijke grootte. Werk eerst met lidmaatschap, combineer daarna verzamelingen en kies of hun waarden in invoegvolgorde of gesorteerde volgorde moeten verschijnen.

3.1 Sla unieke waarden op en test lidmaatschap met HashSet

Een verzameling bevat elke waarde hoogstens één keer. Die past bij vragen zoals “Is deze waarde eerder voorgekomen?” of “Hoeveel verschillende waarden komen voor?” Een HashSet controleert lidmaatschap gemiddeld snel zonder een weergavevolgorde te garanderen.

Voeg waarden toe en controleer ze
import java.util.HashSet;

HashSet<String> visited = new HashSet<>();
boolean first = visited.add("Oslo");
boolean second = visited.add("Lima");
boolean third = visited.add("Oslo");
visited.add("Pune");

De drie opgeslagen booleaanse waarden zijn true, true en false. De tweede “Oslo” komt overeen met een bestaand element en wordt dus niet toegevoegd. De grootte van de verzameling is 3. Een dubbele toevoeging vervangt geen genummerde plek, want een verzameling heeft geen index.

visited.contains("Lima") geeft true terug. visited.remove("Lima") verwijdert de waarde en geeft true terug; als je die verwijdering herhaalt, krijg je false terug. Gebruik een for-each-lus om waarden te doorlopen. Er is geen get(0) voor de eerste waarde van een HashSet.

Verwijder duplicaten uit een lijst
ArrayList<Integer> values = new ArrayList<>();
values.add(3);
values.add(1);
values.add(3);
values.add(2);
values.add(1);
HashSet<Integer> distinct = new HashSet<>(values);

De verzameling heeft drie waarden: {1, 2, 3}. De werkelijke iteratievolgorde is niet gespecificeerd. De oorspronkelijke lijst heeft nog steeds vijf elementen omdat de constructor een aparte collectie maakt.

Gebruik new LinkedHashSet<>(values) om de volgorde van eerste voorkomens te behouden: 3, 1, 2. Gebruik new TreeSet<>(values) om gesorteerde waarden te krijgen: 1, 2, 3. Verzamelingen worden hier tussen accolades geschreven om het lidmaatschap te benadrukken; de standaardmethode toString() van Java gebruikt voor verzamelingen vierkante haken.

Detecteer de eerste herhaling

Het resultaat van add kan de lidmaatschapstest en de toevoeging samen uitvoeren:

HashSet<Integer> seen = new HashSet<>();
for (int number : numbers) {
    if (!seen.add(number)) {
        System.out.println(number);
        break;
    }
}

Voor [4, 7, 2, 7, 4] geeft de lus 7 weer. Dat is de eerste waarde die voor de tweede keer wordt aangetroffen, ook al kwam 4 eerder in de reeks voor. Voordat 7 wordt herhaald, bevat de verzameling 4, 7 en 2. De mislukte toevoeging zorgt ervoor dat de lus stopt.

Weet wat een verzameling je niet kan vertellen

contains vóór elke add controleren is overbodig, omdat add duplicaten al afhandelt. Een lijst met een contains-controle kan waarden ook uniek houden, maar elke zoekactie in de lijst kan alle opgeslagen elementen doorlopen. Een HashSet drukt de regel direct uit.

Gelijkheid is van belang voor je eigen objecten. Een HashSet<Point> heeft een equals op basis van inhoud en een bijpassende hashCode nodig om afzonderlijk gemaakte punten met gelijke coördinaten samen te nemen. Zonder die overschrijvingen blijven afzonderlijke instanties afzonderlijke elementen.

Tot slot meet size() het aantal unieke waarden, niet het aantal voorkomens. De negen woorden in “de kat zag de hond en de kat rende” leveren zes unieke woorden op. Een verzameling vertelt je niet meer dat “de” drie keer voorkwam; gebruik een frequentietabel in een map als die aantallen van belang zijn.

Belangrijkste punten

  • HashSet bewaart unieke waarden zonder index of gegarandeerde volgorde.
  • add geeft false terug als er al een gelijke waarde aanwezig is.
  • Een gekopieerde verzameling verwijdert duplicaten zonder de oorspronkelijke lijst te wijzigen.
  • Gebruik het resultaat van add om een herhaalde waarde te detecteren.
  • De grootte van een verzameling telt unieke waarden; voor frequenties is een map nodig.

3.2 Combineer verzamelingen en behoud hun volgorde

Verzamelingen kunnen groepen beschrijven en hun lidmaatschap vergelijken. Als twee evenementenlijsten dezelfde persoon meerdere keren bevatten, brengt een verzameling elke lijst eerst terug tot de aanwezige personen. Bewerkingen op verzamelingen beantwoorden daarna vragen over minstens één van beide evenementen, beide evenementen of slechts één ervan.

Combineer twee groepen

Laat maandag {Ana, Ben, Cai, Dee} zijn en dinsdag {Ben, Dee, Eva}.

VraagMethode op een kopie van maandagResultaat
Wie was op minstens één van beide dagen aanwezig?addAll(tuesday){Ana, Ben, Cai, Dee, Eva}
Wie was op beide dagen aanwezig?retainAll(tuesday){Ben, Dee}
Wie was alleen op maandag aanwezig?removeAll(tuesday){Ana, Cai}

Deze bewerkingen zijn vereniging, doorsnede en verschil. Ze wijzigen de verzameling waarop ze worden aangeroepen en geven een booleaanse waarde terug die aangeeft of die is gewijzigd. Ze geven geen nieuwe resultaatverzameling terug.

Behoud het origineel

Maak een kopie voordat je het lidmaatschap wijzigt als maandag nog nodig is:

HashSet<String> both = new HashSet<>(monday);
both.retainAll(tuesday);

both begint met alle vier de namen van maandag. retainAll verwijdert Ana en Cai omdat ze op dinsdag ontbreken. Maandag zelf blijft ongewijzigd. Om alleen dinsdag te vinden, begin je met een kopie van dinsdag en verwijder je de namen van maandag. Dat geeft {Eva}. Verschil heeft een richting; als je die omdraait, verandert de vraag.

Controleer deelverzamelingen en gelijkheid

monday.containsAll(group) vraagt of elke waarde in group op maandag aanwezig is. Voor {Ben, Dee} geeft dit true terug: die groep is een deelverzameling van maandag. Het vereist niet dat maandag alleen die twee personen bevat.

Twee verzamelingen zijn gelijk als hun elementen overeenkomen, ongeacht de invoegvolgorde of implementatie. Een HashSet met “x” en “y” is gelijk aan een TreeSet met “y” en “x”. Lidmaatschap bepaalt de gelijkheid van verzamelingen, dus alleen de volgorde kan ze niet ongelijk maken.

Kies een volgorde voor het doorlopen
ImplementatieVolgorde bij het doorlopen van elementen
HashSetGeen garantie
LinkedHashSetInvoegvolgorde
TreeSetGesorteerde volgorde

Alle drie voorkomen duplicaten. Gebruik LinkedHashSet als van belang is wanneer elke naam voor het eerst voorkwam. Gebruik TreeSet als elke doorloop al gesorteerd moet zijn. Voor strings volgt natuurlijk sorteren de tekencodes: kleine letters en hoofdletters gedragen zich niet als één hoofdletterongevoelig alfabet.

Een TreeSet met zijn standaardconstructor heeft elementen nodig die een natuurlijke vergelijking hebben, zoals strings, getallen of objecten die Comparable implementeren. In die verzameling markeert een vergelijkingsresultaat van nul een duplicaat. Een klasse die geen natuurlijke vergelijking biedt, veroorzaakt bij het invoegen een ClassCastException. Een expliciete comparator meegeven is een andere manier om de volgorde van een boomcollectie te definiëren; de standaardvoorbeelden gebruiken de natuurlijke volgorde.

Belangrijkste punten

  • addAll, retainAll en removeAll wijzigen de verzameling waarop ze worden aangeroepen.
  • Kopieer een verzameling eerst als het oorspronkelijke lidmaatschap nog nodig is.
  • containsAll controleert een deelverzameling; gelijkheid van verzamelingen negeert de volgorde.
  • Kies hash-, linked- of tree-implementaties voor respectievelijk een niet-gespecificeerde volgorde, invoegvolgorde of gesorteerde volgorde.
4

Programmeer met de interfaces List, Set en Map

Het type links in een collectiedeclaratie vertelt de rest van het programma welke bewerkingen het kan gebruiken. De klasse rechts biedt die bewerkingen en kan een bepaalde volgorde garanderen. Als je beide kanten leert lezen, wordt collectiecode makkelijker te wijzigen en worden methoden makkelijker opnieuw te gebruiken. Het helpt ook verklaren waarom een lijst, een verzameling en een map zich verschillend gedragen, zelfs als ze vergelijkbare gegevens bevatten.

4.1 Declareer variabelen en parameters met interfacetypen

Een interface beschrijft bewerkingen die een klasse aanbiedt als die de interface implementeert. Met een interface kan een variabele beschrijven wat de code nodig heeft, terwijl de keuze voor de opslag bij een concrete klasse blijft. List, Set en Map zijn interfaces in java.util die met collecties te maken hebben.

Lees beide kanten van een declaratie
List<String> names = new ArrayList<>();
Set<String> tags = new HashSet<>();
Map<String, Integer> counts = new HashMap<>();

Links staat de declaratie van het type van de variabele. Rechts wordt een object gemaakt van een klasse die de interface implementeert. Importeer beide typen, zoals java.util.List en java.util.ArrayList. Je kunt niet new List<>() of new Map<>() schrijven: een interface is geen concreet object dat je kunt maken.

Code die counts gebruikt, kan put, get en entrySet aanroepen omdat Map die declareert. Als alfabetische sleutels van pas komen, verander je de constructie in new TreeMap<>(). Bestaande aanroepen compileren nog steeds. Hun volgorde kan veranderen, omdat implementaties verschillende garanties over volgorde kunnen geven; de interface maakt hun gedrag niet in alle opzichten gelijk.

Accepteer de functionaliteit die een methode nodig heeft

Een methode die alleen lange woorden telt, kan een Collection accepteren:

static int countLong(Collection<String> words, int min) {
    int count = 0;
    for (String word : words) {
        if (word.length() >= min) {
            count++;
        }
    }
    return count;
}

Voor [“a”, “tree”, “house”] en een minimum van 4 geeft de methode 2 terug. Dezelfde methode kan een ArrayList, een LinkedList, een HashSet of List.of(...) ontvangen, omdat die alleen de elementen leest. Een verzameling kan duplicaten al hebben verwijderd en daardoor andere invoergegevens leveren dan een lijst.

Met een interfaceparameter voorkom je dat één specifieke opslagklasse vereist is terwijl de methode die niet nodig heeft. Als posities nodig zijn, accepteer je List. Als opzoeken via een sleutel nodig is, accepteer je Map.

Ken de grenzen van het gedeclareerde type
List<String> names = new ArrayList<>();
names.ensureCapacity(100);  // does not compile

Het object is een ArrayList, maar List declareert ensureCapacity niet. De compiler controleert het gedeclareerde type van de variabele. Gebruik een concreet klassetype als de speciale bewerking daarvan echt nodig is; verander gewone lijstparameters niet alleen om ze bij de klasse van één aanroeper te laten passen.

Plaats Map naast Collection

List en Set breiden Collection uit, dat een groep elementen beschrijft. Deze interface declareert methoden zoals add, remove, contains, size, isEmpty, addAll en clear. Of een wijziging wordt ondersteund, hangt af van de werkelijke collectie.

Map breidt Collection niet uit. Een map slaat koppelingen op en biedt weergaven die collecties zijn: keySet() is een Set, values() is een Collection en entrySet() is een Set met sleutel-waardeparen. Geef counts.values() door aan een methode die een collectie waarden nodig heeft, niet counts zelf.

Een klasse kan meerdere interfaces implementeren. LinkedList implementeert zowel List als Deque, een interface voor een dubbelzijdige wachtrij. Je eigen klasse noemt de interfaces die ze belooft te implementeren na implements, zoals in class Member implements Comparable<Member>.

Belangrijkste punten

  • Declareer links de benodigde interface en maak rechts een object van een klasse die die interface implementeert.
  • Interfaceparameters accepteren verschillende implementaties met de benodigde bewerkingen.
  • Via een variabele zijn alleen methoden beschikbaar die door het type zijn gedeclareerd.
  • List en Set breiden Collection uit; Map biedt collectieweergaven.

4.2 Weet welke garanties List, Set en Map bieden

Kies een interface op basis van de regels die je gegevens nodig hebben. Inhoud die op elkaar lijkt, maakt een lijst, een verzameling en een map niet onderling uitwisselbaar: elk geeft een andere betekenis aan posities, herhaling en gelijkheid.

Vergelijk de garanties
InterfaceWat wordt opgeslagenBelangrijke regel
ListElementen op posities vanaf 0Herhaalde elementen zijn toegestaan
SetUnieke elementenGeen get-bewerking met een index
MapSleutel-waardeparenSleutels zijn uniek; waarden mogen vaker voorkomen

ArrayList en LinkedList implementeren List. HashSet, LinkedHashSet en TreeSet implementeren Set. HashMap, LinkedHashMap en TreeMap implementeren Map. Hashvarianten garanderen geen volgorde bij het doorlopen; linked-varianten behouden de invoegvolgorde; tree-varianten houden elementen of sleutels gesorteerd. Als je een bestaande sleutel opnieuw plaatst in een gewone LinkedHashMap met invoegvolgorde, behoudt die sleutel zijn plaats.

Lees verwijdering uit een lijst met gehele getallen zorgvuldig

Een List<Integer> heeft twee relevante overladen methoden:

List<Integer> numbers = new ArrayList<>(List.of(1, 5, 7));
numbers.remove(1);

Het argument 1 is een int, dus verwijdert Java het element op index 1: de waarde 5. Het resultaat is [1, 7]. Als je opnieuw begint met [1, 5, 7], kiest numbers.remove(Integer.valueOf(1)) voor verwijdering op waarde en blijft [5, 7] over. Het wrapperobject maakt duidelijk welke overladen methode is bedoeld.

Vergelijk inhoud met de juiste regel

Twee lijsten zijn gelijk als dezelfde elementen in dezelfde volgorde voorkomen. Een ArrayList [1, 2] is gelijk aan een LinkedList [1, 2], maar niet aan een lijst [2, 1]. Twee verzamelingen vergelijken het lidmaatschap en negeren de volgorde. Twee maps vergelijken koppelingen, dus beïnvloedt de invoegvolgorde hun gelijkheid niet. Hun concrete klassen kunnen verschillen terwijl hun inhoud volgens de regel van de interface gelijk is.

Herken niet-wijzigbare collecties
List<String> labels = List.of("a", "b");
Set<Integer> levels = Set.of(1, 2, 3);
Map<String, Double> prices = Map.of("tea", 2.0, "coffee", 2.5);

Deze fabrieksmethoden geven niet-wijzigbare collecties terug. Pogingen om de inhoud toe te voegen, te verwijderen, te vervangen of te sorteren werpen een UnsupportedOperationException op. Map.of accepteert maximaal tien sleutel-waardeparen.

Alle drie wijzen ze null-elementen, -sleutels of -waarden af met een NullPointerException. Set.of wijst dubbele elementen af en Map.of dubbele sleutels, met een IllegalArgumentException. List.of staat duplicaten toe omdat een lijst een element mag herhalen. De iteratievolgorde van de verzamelingen en maps die deze fabrieksmethoden maken, is niet gespecificeerd.

Kopieer als wijzigingen nodig zijn

new ArrayList<>(labels) maakt een wijzigbare lijst met dezelfde elementen. new HashSet<>(someList) en new HashMap<>(someMap) maken op dezelfde manier afzonderlijke collectiestructuren.

Deze kopieën zijn ondiep: ze bevatten dezelfde elementreferenties. Als je een element uit een kopie verwijdert, blijft de oorspronkelijke structuur intact, maar als je via een van beide collecties een veranderlijk object wijzigt, verandert het gedeelde object. Een niet-wijzigbare collectie verhindert wijzigingen aan de structuur; die bevriest niet elk object dat erin is opgeslagen.

Belangrijkste punten

  • Lijsten hebben posities en duplicaten; verzamelingen hebben unieke elementen; maps hebben unieke sleutels.
  • remove(1) op een lijst met gehele getallen verwijdert op index; remove(Integer.valueOf(1)) verwijdert op waarde.
  • Gelijkheid van lijsten controleert de volgorde; gelijkheid van verzamelingen en maps controleert de inhoud zonder de invoegvolgorde.
  • Collecties van of-fabrieksmethoden zijn niet wijzigbaar en wijzen null-waarden af.
  • Set.of wijst dubbele elementen af; Map.of wijst dubbele sleutels af.
  • Een wijzigbare kopie heeft een aparte collectiestructuur, maar deelt de elementreferenties.
5

Sorteer collecties met Comparable

Sorteren plaatst waarden in een volgorde die andere code kan gebruiken. Getallen en strings kennen hun natuurlijke volgorde al; objecten van je eigen klassen hebben een expliciete regel nodig. Volg een lijst tijdens een sortering en schrijf daarna een vergelijking die veilig omgaat met getallen, tekst en gelijke sorteerrangen. De regel is ook buiten lijsten van belang: een gesorteerde verzameling of map gebruikt die eveneens om te bepalen wanneer twee elementen of sleutels dezelfde plaats innemen.

5.1 Sorteer lijsten met getallen en strings

Een lijst behoudt een volgorde, maar die volgorde kan eenvoudigweg weergeven hoe waarden zijn binnengekomen. Sorteren herschikt de lijst met een vergelijkingsregel. Java biedt al een natuurlijke volgorde voor getallen en strings.

Sorteer een wijzigbare lijst ter plaatse
List<Double> values = new ArrayList<>(List.of(3.5, -1.0, 2.25));
Collections.sort(values);

Importeer java.util.Collections. Dezelfde lijst bevat nu [-1,0; 2,25; 3,5]. De sortering geeft void terug, dus values = Collections.sort(values) compileert niet. values.sort(null) sorteert ook in natuurlijke volgorde. Gebruik voor een array Arrays.sort(array); een array met 5, 2 en 8 wordt 2, 5, 8.

Voorspel de stringvolgorde teken voor teken

Bij het vergelijken van strings wordt naar het eerste verschillende teken gekeken. Als de ene string een prefix van de andere is, komt de kortere eerst. Zo komt “appel” vóór “appels”.

De lijst [“pear”, “Banana”, “apple”, “10”, “9”] wordt gesorteerd tot [“10”, “9”, “Banana”, “apple”, “pear”]. Voor deze tekens komen cijfers vóór hoofdletters en hoofdletters vóór kleine letters. “10” komt vóór “9” omdat ‘1’ vóór ‘9’ komt; de stringvolgorde interpreteert cijferstrings niet als gehele getallen. Sla numerieke gegevens op als getallen wanneer een numerieke volgorde nodig is.

Gebruik kant-en-klare alternatieve volgorden
names.sort(String.CASE_INSENSITIVE_ORDER);
values.sort(Collections.reverseOrder());

De eerste aanroep ordent [“pear”, “Banana”, “apple”] als [“apple”, “Banana”, “pear”] zonder de opgeslagen hoofdletters en kleine letters te wijzigen. De tweede gebruikt aflopende natuurlijke volgorde. De getallen 4, 9 en 1 worden 9, 4 en 1. Deze argumenten zijn comparators, objecten die een alternatieve volgorde bieden.

Collections.reverse(list) keert alleen de huidige reeks om. Dit levert een aflopende volgorde op als die reeks al oplopend was gesorteerd; op zichzelf sorteert het geen willekeurige lijst.

Behoud de volgorde bij gelijke sorteerrangen

Het sorteren van lijsten is stabiel: elementen die bij vergelijking gelijk zijn, behouden hun eerdere onderlinge volgorde. Als een vergelijking die alleen scores gebruikt twee personen als gelijk beoordeelt, blijft hun eerdere volgorde in de lijst behouden. Stabiliteit bewaart die invoervolgorde; er ontstaat niet vanzelf een aanvullend alfabetisch sorteercriterium.

Herken fouten en handige methoden

Een lijst van List.of(...) kan niet ter plaatse worden gesorteerd. Kopieer die eerst naar een ArrayList. Voor een klasse zonder Comparable mislukt de typecontrole van Collections.sort(list) bij het compileren. Als je list.sort(null) op zulke objecten aanroept, mislukt dat tijdens de uitvoering met een ClassCastException wanneer een vergelijking nodig is.

Collections.max(collection) en Collections.min(collection) vinden de grootste en kleinste elementen volgens de natuurlijke volgorde zonder de collectie te herschikken. Ze werpen een NoSuchElementException op voor een lege collectie.

Voor gesorteerde mapsleutels kun je map.keySet() naar een ArrayList kopiëren en de kopie sorteren, of een TreeMap gebruiken. Het sorteren van een gekopieerde sleutellijst laat de eigen iteratievolgorde van de map ongewijzigd.

Belangrijkste punten

  • Collections.sort wijzigt een wijzigbare lijst ter plaatse en geeft void terug.
  • De natuurlijke volgorde van strings vergelijkt tekens, niet de numerieke waarden in tekst.
  • Gebruik kant-en-klare comparators voor een omgekeerde of hoofdletterongevoelige volgorde.
  • Stabiel sorteren behoudt de eerdere onderlinge volgorde van elementen met gelijke sorteerrang.
  • Kopieer een niet-wijzigbare lijst voordat je die sorteert.
  • min en max vinden extrema zonder te sorteren.

5.2 Implementeer Comparable in je eigen klasse

Java kan niet raden of een lid eerst op naam, lengte of een ander veld moet komen. Implementeer Comparable om de klasse één natuurlijke volgorde te geven. Sorteercode kan dan elk object vragen zichzelf te vergelijken met een ander object van die klasse.

Schrijf de vergelijkingsmethode
class Member implements Comparable<Member> {
    private String name;
    private int height;

    Member(String name, int height) {
        this.name = name;
        this.height = height;
    }

    @Override
    public int compareTo(Member other) {
        return Integer.compare(this.height, other.height);
    }
}

De lengte wordt gemeten in centimeters. Comparable<Member> geeft aan dat het andere object een Member is; een expliciete typeconversie is niet nodig. public int compareTo(Member other) is de vereiste methode. De standaardinterface Comparable staat in java.lang, dus is daarvoor geen import nodig.

Bij a.compareTo(b) plaatst een negatief resultaat a vóór b, zet nul ze op dezelfde vergelijkingspositie en plaatst een positief resultaat a na b. Alleen het teken is van belang: -35 is een even geldig negatief resultaat als -1.

Volg de volgorde

Met de vergelijking op lengte worden Ana 172, Ben 165 en Cai 180 gesorteerd tot Ben 165, Ana 172 en Cai 180. Verwissel de argumenten om langere leden eerst te plaatsen:

return Integer.compare(other.height, this.height);

Verander de regel bewust. Als je de argumenten omdraait, keer je de sorteerrichting van dat veld om; je verandert niet de betekenis van lengte of de gegevens van een lid.

Vergelijk gehele numerieke waarden veilig

Aftrekken lijkt handig, maar kan het verkeerde teken teruggeven als een int overloopt. Voor -2.000.000.000 en 2.000.000.000 geeft het aftrekken van het tweede getal van het eerste na overloop 294.967.296, een positief resultaat. Integer.compare geeft terecht een negatief resultaat terug.

Gebruik voor velden met kommagetallen Double.compare(this.price, other.price). Een verschil expliciet omzetten naar int laat informatie verloren gaan: (int) (1.8 - 1.5) is 0, zodat ongelijke prijzen dezelfde sorteerrang krijgen. Een vergelijkingsmethode behoudt de volgorde zonder het verschil af te kappen.

Vergelijk tekst en gebruik de regel opnieuw

Geef voor een volgorde op naam this.name.compareTo(other.name) terug. Deze methode volgt de tekenvolgorde van de string. compareToIgnoreCase biedt een hoofdletterongevoelige tekstvergelijking wanneer dat de bedoelde regel voor het veld is.

Zodra een klasse een natuurlijke volgorde definieert, kunnen bewerkingen zoals Collections.sort, Collections.max en de standaardvergelijkingen van TreeSet of TreeMap die gebruiken. Een klasse kan ook andere interfaces implementeren, gescheiden door komma’s na implements.

Er is één natuurlijke volgorde voor de klasse; er wordt niet voor elke lijst een andere compareTo gekozen. Gebruik aparte comparatorobjecten wanneer de ene context een volgorde op naam nodig heeft en de andere een volgorde op lengte. Een vergelijking die alleen lengte gebruikt, geeft ook alle gelijke lengtes dezelfde sorteerrang; of dat aanvaardbaar is, wordt vooral belangrijk bij gesorteerde verzamelingen.

Belangrijkste punten

  • Implementeer Comparable<YourClass> met een publieke methode compareTo.
  • Negatieve resultaten, nul en positieve resultaten betekenen respectievelijk ervoor, gelijke sorteerrang en erna.
  • Gebruik Integer.compare en Double.compare om getallen veilig te ordenen.
  • Verwissel vergelijkingsargumenten om de sorteerrichting van een veld om te keren.
  • Eén klasse heeft één natuurlijke volgorde; comparators bieden andere volgorden.

5.3 Gebruik aanvullende sorteercriteria en werk met gesorteerde verzamelingen en maps

Een primaire vergelijking laat vaak gelijke sorteerrangen over. Twee films kunnen hetzelfde jaar hebben of twee spelers dezelfde score. Een aanvullend sorteercriterium geeft het volgende veld pas een beurt als de eerdere velden bij vergelijking gelijk zijn.

Vergelijk velden in volgorde van prioriteit
@Override
public int compareTo(Film other) {
    int byYear = Integer.compare(this.year, other.year);
    if (byYear != 0) {
        return byYear;
    }
    return this.title.compareTo(other.title);
}

Het jaar is de hoofdregel. De titel is alleen van belang als de jaren gelijk zijn. Up (2009), Avatar (2009) en Alien (1979) worden gesorteerd tot Alien (1979), Avatar (2009), Up (2009). Als je eerst titels vergelijkt, krijgen die voorrang op het jaar en voer je een andere sorteertaak uit.

De richtingen kunnen per veld verschillen. Voor de hoogste punten eerst en namen van A tot Z begin je met Integer.compare(other.points, this.points). Geef bij nul this.name.compareTo(other.name) terug. Als je de hele uiteindelijke lijst zou omkeren, zou je ook de namen binnen gelijke scores omkeren.

Begrijp de duplicaatregel van een gesorteerde verzameling

Een standaard TreeSet<Member> gebruikt de natuurlijke vergelijking zowel om elementen te ordenen als om te bepalen wanneer een element al aanwezig is. Als Member.compareTo alleen lengte gebruikt, levert het vergelijken van Ana 172 en Dee 172 nul op. Het toevoegen van Ana geeft true terug; het toevoegen van Dee geeft false terug. Ana blijft het opgeslagen element, ook als equals de twee leden als verschillend beschouwt.

Een lijst kan beide objecten met gelijke sorteerrang behouden; een tree-verzameling geeft ze één vergelijkingspositie. Voeg het nodige aanvullende sorteercriterium toe als ze afzonderlijk in de verzameling moeten staan.

Stem vergelijking af op gelijkheid

Een volgorde is consistent met equals wanneer de vergelijking nul teruggeeft dan en slechts dan als equals true teruggeeft. Voor een klasse waarvan de gelijkheid lengte en naam gebruikt, kan vergelijken op lengte en daarna naam aan deze regel voldoen. Als gelijkheid een andere identiteit gebruikt, zoals een lid-ID, zorgt alleen naam toevoegen als aanvullend sorteercriterium niet voor consistentie.

De vergelijking moet zich ook gedragen als een geldige volgorde. Als a vóór b komt, moet de omgekeerde vergelijking b na a plaatsen. Als a vóór b komt en b vóór c, moet a vóór c komen. Vergelijkingsmethoden voor hele velden gebruiken in een vaste volgorde van prioriteit ondersteunt deze regels. Een inconsistente methode kan resultaten verkeerd ordenen of ervoor zorgen dat een sortering een IllegalArgumentException opwerpt.

Houd ook mapsleutels gesorteerd

Een TreeMap sorteert sleutels, geen waarden. Voor de woordtellingen van “de kat zag de hond en de kat rende” is de eerste sleutel “de” en de laatste “zag”. firstKey() en lastKey() geven die uiterste sleutels. Declareer een TreeMap of een passende interface voor gesorteerde maps wanneer je methoden aanroept die de gewone Map niet declareert.

De sleutelvergelijking bepaalt ook welke sleutels overeenkomen. Een tweede sleutel die bij vergelijking nul oplevert, werkt de bestaande koppeling bij, ook als equals de objecten onderscheidt. Standaard hebben tree-collecties elementen of sleutels nodig die van nature vergelijkbaar zijn; als je een object zonder geschikte vergelijking invoegt, wordt een ClassCastException opgeworpen. Een expliciet meegegeven comparator kan een andere volgorde definiëren.

Belangrijkste punten

  • Vergelijk eerst het primaire veld en raadpleeg latere velden alleen bij een gelijke sorteerrang.
  • Keer alleen de velden om die een aflopende volgorde nodig hebben.
  • Tree-collecties behandelen vergelijkingsresultaat nul als hetzelfde element of dezelfde sleutel.
  • Consistentie met equals vereist vergelijkingsresultaat nul precies wanneer gelijkheid waar is.
  • TreeMap sorteert sleutels; de methoden voor de uiteinden geven de uiterste sleutels terug.
  • Een vergelijking moet tekens consequent omkeren en de volgorde over drietallen behouden.
6

Kies de juiste collectie voor een taak

De keuze voor een collectie begint bij de vragen die het programma moet beantwoorden: op positie, op lidmaatschap of via een aparte sleutel. Volgorde en duplicaten beperken de keuze verder. Als de gegevens eenmaal bij de taak passen, vergelijk je hoe de veelgebruikte bewerkingen groeien naarmate er meer waarden bijkomen. Een kleine verandering, zoals één verzameling maken vóór een lus, kan herhaalde zoekacties wegnemen zonder het programma moeilijker leesbaar te maken.

6.1 Vergelijk de kosten van veelgebruikte collectiebewerkingen

De kosten van een bewerking beschrijven hoe het werk groeit met het aantal opgeslagen elementen. Zo kun je code herkennen die snel is voor een klein voorbeeld, maar traag wordt als de collectie groot wordt.

Vergelijk groei, geen seconden

Constante tijd, O(1), blijft ongeveer onafhankelijk van de collectiegrootte. Lineaire tijd, O(n), kan evenredig met het aantal elementen groeien. Logaritmische tijd, O(log n), groeit langzaam als de grootte toeneemt. Deze aanduidingen beschrijven groei, geen exacte uitvoeringstijden op een bepaalde computer.

CollectieBewerkingKosten
ArrayListget(i), set(i, x)Constant
ArrayListAchteraan toevoegenGemiddeld constant
ArrayListcontains, indexOf, verwijderen op waardeLineair
ArrayListToevoegen of verwijderen nabij het beginLineair
HashMap / HashSetGewone zoekactie op sleutel of lidmaatschapstest, toevoegen, verwijderenGemiddeld constant bij goed gespreide hashcodes
TreeMap / TreeSetGewone zoekactie, toevoegen, verwijderenLogaritmisch
LinkedListToevoegen of verwijderen aan beide uiteindenConstant
LinkedListget(i) in het algemeenLineair

Een zoekactie in een ArrayList kan elk element controleren; wijzigingen aan het begin verschuiven latere elementen. Een LinkedList moet naar een positie lopen, dus herhaald benaderen via een index kan veel kosten. ArrayList is een bruikbare standaardkeuze voor gewoon werk met lijsten.

Herken het herhaald doorzoeken

Stel dat een programma 10.000 namen controleert tegen een lijst met 100.000 namen. Voor elke naam list.contains(name) aanroepen kan maximaal 1.000.000.000 gelijkheidscontroles vereisen. Een methodeaanroep die er snel uitziet, blijft bij dit gebruik een volledige zoekactie.

Maak één keer een verzameling voor lidmaatschap:

Set<String> allowed = new HashSet<>(allowedNames);
int matches = 0;
for (String name : incomingNames) {
    if (allowed.contains(name)) {
        matches++;
    }
}

Het opbouwen van de verzameling met 100.000 elementen kost werk, gevolgd door 10.000 lidmaatschapscontroles die gemiddeld constante tijd kosten. Als je beide fasen meetelt, groeit het totaal ongeveer met de som van de twee invoergroottes, in plaats van met hun product. Als je de verzameling binnen de lus opnieuw zou opbouwen, herhaal je het opbouwwerk en gaat dat voordeel verloren.

Lees gemiddelde garanties correct

Hashbewerkingen vertrouwen op sleutels waarvan de hashcodes waarden goed spreiden. Voor elk object één constante hashcode teruggeven kan nog steeds voldoen aan de eisen voor correcte gelijkheid, maar maakt het opzoeken traag. Het is geen kosteloze manier om het schrijven van een bruikbare hashmethode te vermijden.

Tree-collecties behouden een gesorteerde volgorde met basisbewerkingen in logaritmische tijd. Een verdubbeling van het aantal elementen voegt maar een kleine hoeveelheid zoekwerk toe. Voor 100.000 elementen is een logaritme met grondtal twee ongeveer 16,6; dit geeft een indruk van de omvang van de zoekactie, geen exacte garantie van 17 vergelijkingen bij elke zoekactie in een Java-boom.

Houd rekening met de hele taak

Een extra verzameling opbouwen kost tijd en geheugen. Voor enkele elementen of één zoekactie kan de oorspronkelijke lijst voldoende zijn. Voor herhaalde lidmaatschapscontroles neemt één herbruikbare verzameling vaak de belangrijkste kosten weg. Begin bij het vereiste gedrag en onderzoek daarna de bewerkingen die het vaakst worden herhaald.

Belangrijkste punten

  • Groeiaanduidingen beschrijven hoe de kosten meegroeien, geen gemeten aantal seconden.
  • ArrayList biedt snelle toegang via een index, maar zoekacties en wijzigingen aan het begin kosten lineaire tijd.
  • Zoekacties met hashing kosten gemiddeld constante tijd bij geschikte hashcodes; zoekacties in een boom kosten logaritmische tijd.
  • Bouw één keer een verzameling voor lidmaatschap om herhaald doorzoeken van lijsten te vervangen.
  • Neem opbouwtijd en geheugengebruik mee wanneer je volledige oplossingen vergelijkt.

6.2 Kies een collectie die bij de taak past

De juiste collectie bewaart de informatie die het programma nodig heeft en maakt de belangrijkste vragen eenvoudig uit te drukken. Bepaal de regels voor de gegevens voordat je een vertrouwde klassenaam kiest.

Vraag wat een element identificeert
Belangrijkste behoefteEerste keuzeVoorbeeld
Een waarde vinden via een aparte sleutelMapProductcode naar prijs
Lidmaatschap testen zonder duplicatenSetBezette gebruikersnamen
Posities, volgorde of herhaalde elementen behoudenListEen afspeellijst met herhaalde nummers
Een vast aantal plaatsen behoudenArrayTwaalf maandelijkse neerslagmetingen

Een double[12] kan de neerslag in millimeters bevatten wanneer van elke plaats de maand bekend is. Een map met alleen posities 0, 1, 2 enzovoort als sleutels voegt een laag toe die een lijst of array al biedt.

Kies de volgorde die je nodig hebt

Gebruik voor maps en verzamelingen HashMap of HashSet als geen volgorde vereist is, LinkedHashMap of LinkedHashSet voor invoegvolgorde en TreeMap of TreeSet voor gesorteerde sleutels of elementen. Begin voor een lijst voor algemeen gebruik met ArrayList.

Alfabetisch weergegeven woordtellingen passen bij een TreeMap<String, Integer>. Een lijst met unieke labels in de volgorde waarin ze voor het eerst voorkwamen, past bij LinkedHashSet<String>. Herhaalde nummers vereisen een lijst, ook als de nummers elders in een verzameling zijn opgeslagen: herhalingen weggooien zou de afspeellijst veranderen.

Combineer collecties als de gegevens uit lagen bestaan

Studenten per cursus kunnen een Map<String, List<String>> vormen; elke waarde is een geordende lijst met inschrijvingen. Labels per artikel kunnen een Map<String, Set<String>> vormen; elk artikel krijgt unieke labels. Een ranglijst kan een List<Player> zijn die is gesorteerd volgens de natuurlijke vergelijking van de speler.

De keuze voor de buitenste en binnenste collectie beantwoordt verschillende vragen. Als cursussen alfabetisch moeten worden vermeld en studenten in volgorde van inschrijving moeten worden bewaard, gebruik dan buiten een TreeMap en binnen een lijst. Het sorteren van de sleutels sorteert de lijsten niet. Als dubbele inschrijvingen moeten worden genegeerd, gebruik dan een verzameling voor de binnenste groepen.

Houd verwante gegevens bij elkaar

Twee parallelle lijsten, één voor namen en één voor telefoonnummers, vertrouwen op overeenkomende posities. Als je een naam zonder het bijbehorende nummer verwijdert, klopt elke latere koppeling niet meer. Als namen personen uniek identificeren, kan een map de koppeling bewaren. Als namen vaker voorkomen of meerdere velden bij één persoon horen, bewaar dan objecten die personen voorstellen in een lijst of indexeer ze op een unieke ID.

Een lijst steeds opnieuw op een veld doorzoeken is een ander signaal om een indexmap te overwegen. Bewaar de lijst ook als weergavevolgorde en herhaalde elementen van belang zijn, maar werk beide structuren samen bij wanneer gegevens worden toegevoegd of verwijderd.

Controleer de elementregels en het gedeclareerde type

Gebruik een interfacedeclaratie zoals Map<String, Double> prices = new HashMap<>(); zodat aanroepers kunnen vertrouwen op de mapbewerkingen die ze nodig hebben. Hashcollecties hebben zinvolle gelijkheid en bijpassende hashcodes nodig voor zelfgemaakte sleutels of elementen. Standaard hebben tree-collecties een natuurlijke vergelijking nodig die precies de waarden onderscheidt die de collectie moet bewaren. Deze regels horen bij het laten weergeven van de bedoelde gegevens door de gekozen collectie.

Belangrijkste punten

  • Kies maps om op sleutel te zoeken, verzamelingen voor lidmaatschap en lijsten voor posities of herhalingen.
  • Arrays kunnen een vast aantal plaatsen bevatten, ook met primitieve waarden.
  • Kies bewust voor invoegvolgorde of gesorteerde volgorde.
  • Met geneste collecties kunnen buitenste sleutels en binnenste groepen verschillende regels volgen.
  • Houd verwante velden bij elkaar en onderhoud meerdere indexen via gemeenschappelijke methoden.
  • Stem gelijkheids- en vergelijkingsregels af op de waarden die de collectie moet bewaren.

HashMaps en collecties in Java: voorbeelden

6 Walkthroughs

1

Volg een voorraadmap van opslaan tot opzoeken

13 stappen
Volg wijzigingen, bekijk sleutel-waardeparen veilig en maak zelfgedefinieerde sleutels vindbaar.
  1. 1
    IntroductieBegin met een vraag over een product

    Een voorraadprogramma moet de vraag “Hoeveel mappen zijn beschikbaar?” kunnen beantwoorden. Een map maakt de productnaam de sleutel en de hoeveelheid de waarde. Volg één map tijdens een vervanging, een zoekactie naar een ontbrekende sleutel en het opschonen. Bekijk daarna waarom een zelfgedefinieerde sleutel kan falen, ook als de velden er juist uitzien. Elke zoekactie hangt af van wat Java als dezelfde sleutel beschouwt.

  2. 2
    UitlegMaak één koppeling per sleutel

    Maak HashMap<String, Integer> stock = new HashMap<>();. String beschrijft de sleutels; Integer beschrijft de waarden. De map gebruikt referentietypen, dus int kan niet het typeargument voor de waarde zijn. Java zet een literal zoals 6 via autoboxing om wanneer stock.put("folder", 6) die opslaat. Met de diamantnotatie rechts kan Java de twee typen afleiden.

  3. 3
    VoorbeeldVervang een hoeveelheid

    Voer deze bijwerkingen op volgorde uit:

    stock.put("folder", 6);
    stock.put("clip", 11);
    Integer old = stock.put("folder", 8);
    

    De laatste aanroep vindt de bestaande sleutel voor mappen, slaat 8 op en geeft 6 terug in old. Er zijn nog steeds twee sleutels. Een map bewaart de meest recente waarde voor een sleutel; die telt hoeveelheden niet automatisch op en houdt er geen geschiedenis van bij.

  4. 4
    UitdagingLees zonder toe te voegen

    Wat zijn n en stock.size() na deze leesactie? De map bevat nog steeds map 8 en paperclip 11.

    int n = stock.getOrDefault("tape", 0);
    

    ---reveal---

    n is 0 en de grootte blijft 2. De standaardwaarde is een resultaat voor een ontbrekende sleutel, geen toegevoegd sleutel-waardepaar. Als je in plaats daarvan leest met get("tape"), krijg je null terug, wat niet via unboxing kan worden omgezet naar een int.

  5. 5
    UitlegLees sleutels en waarden samen

    Een lus over sleutel-waardeparen biedt elke sleutel samen met de waarde:

    for (Map.Entry<String, Integer> e : stock.entrySet()) {
        System.out.println(e.getKey() + ": " + e.getValue());
    }
    

    Importeer java.util.Map. De lus kan beide koppelingen tonen zonder een aparte get. Als alleen een totaal nodig is, doorloop je stock.values() en tel je de hoeveelheden op; herhaalde hoeveelheden dragen nog steeds afzonderlijk bij.

  6. 6
    KernpuntLeid het eerste paar niet af

    De uitvoer kan map vóór paperclip of paperclip vóór map vermelden. HashMap garandeert geen van beide volgorden. Een resultaat zoals een som wordt daardoor niet beïnvloed, maar een regel als “bewaar de eerste score bij een gelijke stand” kan afhangen van de volgorde van doorlopen. Kies LinkedHashMap voor invoegvolgorde of TreeMap voor gesorteerde sleutels en geef gelijke maxima een expliciete regel als de winnaar voorspelbaar moet zijn.

  7. 7
    VoorbeeldVerwijder tijdens het doorlopen

    Stel dat map nu 0 is en paperclip 11. Verwijder hoeveelheden van nul met een iterator:

    Iterator<Map.Entry<String, Integer>> it =
        stock.entrySet().iterator();
    while (it.hasNext()) {
        if (it.next().getValue() == 0) {
            it.remove();
        }
    }
    

    De iterator verwijdert het huidige sleutel-waardepaar en gaat veilig verder. Als je stock.remove aanroept vanuit een for-each-doorloop, kan dat een ConcurrentModificationException veroorzaken.

  8. 8
    UitdagingMaak een aparte kopie van de sleutels

    Vóór het opschonen wordt keys gemaakt met new ArrayList<>(stock.keySet()). Wat gebeurt er met de voorraadmap als keys.remove("folder") wordt aangeroepen?

    ---reveal---

    De map behoudt de koppeling voor mappen. keys is een aparte lijst met de sleutels die bestonden toen de kopie werd gemaakt. Als je iets uit stock.keySet() zelf zou verwijderen, zou het sleutel-waardepaar uit de map verdwijnen, omdat dat object een gekoppelde weergave is.

  9. 9
    VoorbeeldProbeer een zelfgedefinieerde sleutel

    Stel dat Bin de velden row en column heeft en geen gelijkheidsmethoden overschrijft. Sla een label op met new Bin(3, 4) en zoek het daarna op met een andere new Bin(3, 4). De zoekactie geeft null terug. Dit zijn twee verschillende objecten en de overgeërfde Object.equals gebruikt identiteit. Overeenkomende veldwaarden zijn nog niet vastgelegd als regel voor overeenkomende sleutels.

  10. 10
    UitlegStem gelijkheid en hashcodes op elkaar af

    Voor identiteit van bakken op basis van coördinaten overschrijf je equals(Object other) om rij en kolom te vergelijken en overschrijf je hashCode() met dezelfde velden, bijvoorbeeld Objects.hash(row, column). Gelijke coördinaten moeten gelijke hashcodes opleveren. Een overeenkomende hashcode alleen stelt geen gelijkheid vast; de gelijkheidscontrole onderscheidt nog steeds verschillende sleutels op basis van coördinaten.

  11. 11
    UitdagingHerken een overladen methode

    Een klasse definieert public boolean equals(Bin other) en hashCode() op basis van haar coördinaten. Waarom kan een zoekactie met een afzonderlijke bak die gelijk lijkt toch mislukken?

    ---reveal---

    De parameter moet Object zijn om de gelijkheidsmethode van Java te overschrijven. De methode met een Bin-parameter is een overladen methode, waardoor de overgeërfde gelijkheid op basis van identiteit blijft gelden. Als je @Override aan die verkeerde signatuur toevoegt, maakt de compiler de fout zichtbaar.

  12. 12
    UitdagingHerstel een ontwerp met een veranderende sleutel

    Een baksleutel gebruikt rij en kolom in zowel de gelijkheidsmethode als de hashcodemethode. Het programma wijzigt de rij terwijl de sleutel is opgeslagen en kan daarna het label niet vinden. Hoe moet het programma de locatie bijwerken en daarna lege labels veilig verwijderen tijdens het doorlopen?

    ---reveal---

    Verwijder de koppeling voordat je de sleutel wijzigt en voeg die daarna opnieuw toe. Gebruik voor het opschonen tijdens het doorlopen de eigen verwijdermethode van de iterator over sleutel-waardeparen. Stabiele sleutelidentiteit en veilig doorlopen lossen verschillende delen van deze bijwerking op.

  13. 13
    SamenvattingHoud een controlelijst voor mapbijwerkingen bij

    Bepaal bij een ontbrekend zoekresultaat of een standaardwaarde of een expliciete controle op afwezigheid bij de taak past. Bepaal bij een lus of de volgorde van belang is en of sleutels worden verwijderd. Controleer bij een zelfgedefinieerde sleutel de exacte signatuur equals(Object), overeenkomstige hashvelden en stabiele identiteit. Deze controles vinden verschillende oorzaken van hetzelfde probleem: een koppeling die het programma niet kan gebruiken zoals verwacht.

2

Bouw aanwezigheidsinformatie op terwijl records binnenkomen

12 stappen
Tel records, groepeer unieke deelnemers en houd zoekindexen consistent.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieZet binnenkomende gegevens om in bruikbare antwoorden
  2. 2
    VoorbeeldBegin een sessietelling
  3. 3
    VoorbeeldOnderscheid unieke sessies van records
  4. 4
    UitdagingHerstel een telling die wordt teruggezet
  5. 5
    UitlegMaak een groep één keer aan
  6. 6
    VoorbeeldVolg de binnenste referentie
  7. 7
    UitdagingZoek de fout met een gedeelde groep
  8. 8
    UitlegIndexeer op een identificerende sleutel
  9. 9
    KernpuntWijzig één object op meerdere plaatsen
  10. 10
    UitdagingHoud verwijderingen consistent
  11. 11
    UitdagingCombineer tellingen met uniek lidmaatschap
  12. 12
    SamenvattingControleer een eerste invoerwaarde en een herhaling
3

Vergelijk twee groepen aanwezigen

9 stappen
Gebruik lidmaatschap van verzamelingen, behoud de originelen en rapporteer het juiste verschil.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieVraag wie aanwezig was, niet hoe vaak
  2. 2
    VoorbeeldVoeg herhaalde scans samen
  3. 3
    UitdagingStop bij de eerste herhaalde invoerwaarde
  4. 4
    VoorbeeldBehoud alleen gemeenschappelijke leden
  5. 5
    UitlegKies de richting van het verschil
  6. 6
    UitdagingTest een geselecteerde groep
  7. 7
    TipKies een bruikbare volgorde voor het overzicht
  8. 8
    UitdagingMaak een gesorteerd overzicht van afwezigen
  9. 9
    SamenvattingLees de ontvangende verzameling als begingroep
4

Lees collectiedeclaraties en kopieën

10 stappen
Gebruik interfaces, herken problemen met overladen methoden en onderscheid de structuur van gedeelde objecten.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieLees beide kanten van de declaratie
  2. 2
    UitlegDeclareer wat de aanroeper nodig heeft
  3. 3
    VoorbeeldGebruik een ruimere parameter om te lezen
  4. 4
    UitdagingOnderzoek de ontbrekende methode
  5. 5
    VerbandKies de betekenis van de inhoud
  6. 6
    VoorbeeldVolg verwijdering bij gehele getallen
  7. 7
    UitdagingKopieer voordat je sorteert
  8. 8
    KernpuntOnderscheid objectwijzigingen van lijstwijzigingen
  9. 9
    UitdagingGeef de juiste mapweergave door
  10. 10
    SamenvattingControleer type, bewerking en object
5

Maak een ranglijst die de juiste gelijke scores behoudt

15 stappen
Sorteer strings en objecten, schrijf veilige vergelijkingen en controleer lidmaatschap van een gesorteerde verzameling.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieKies wat eerst komt
  2. 2
    VoorbeeldSorteer dezelfde lijst
  3. 3
    UitlegLees het eerste verschillende teken
  4. 4
    UitdagingGebruik een aangeboden volgorde
  5. 5
    UitlegGeef een klasse één natuurlijke volgorde
  6. 6
    VoorbeeldVoorkom een onterechte gelijke sorteerrang bij getallen
  7. 7
    UitdagingKeer het numerieke veld om
  8. 8
    VoorbeeldGebruik alleen bij echte gelijke standen een aanvullend criterium
  9. 9
    VoorbeeldDoorloop de rangschikking
  10. 10
    UitdagingBekijk wat een tree-verzameling behoudt
  11. 11
    KernpuntStem volgorde af op identiteit
  12. 12
    VerbandControleer de sleutel van een gesorteerde map
  13. 13
    UitdagingBehoud elk resultaat in een gesorteerde lijst
  14. 14
    TipLaat de regel werken voor drietallen
  15. 15
    SamenvattingControleer een vergelijking op twee plaatsen
6

Kies structuren voor een cursuslijst

10 stappen
Stem opzoeken, lidmaatschap, volgorde en kosten op elkaar af zonder herhaald te doorzoeken.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieMaak een lijst van de vragen van het programma
  2. 2
    VoorbeeldHerken de zoekactie binnen de lus
  3. 3
    UitlegMaak één keer een verzameling voor lidmaatschap
  4. 4
    UitdagingVergelijk groeiende invoer
  5. 5
    VoorbeeldBehoud herhaalde inschrijvingsrecords
  6. 6
    UitlegKies de buitenste en binnenste volgorde
  7. 7
    UitdagingHerstel de verkeerde duplicaatregel
  8. 8
    TipHoud rekening met de kosten van de gewenste volgorde
  9. 9
    UitdagingCombineer het uiteindelijke ontwerp
  10. 10
    SamenvattingKies gedrag voordat je snelheid meet

HashMaps en collecties in Java: oefenvragen

50 Oefenvragen in 5 sets

Set 1: Lees maps betrouwbaar en werk ze bij10 Oefenvragen

Vraag 1 van 10

Een lege HashMap<String, Integer> ontvangt put("brush", 5) en daarna put("brush", 14). Wat zijn de grootte en de waarde voor "brush"?
  1. Grootte 2; waarde 14.
  2. Grootte 1; waarde 14.
  3. Grootte 1; waarde 19.
  4. Grootte 2; waarde 5.
Toon antwoordVerberg antwoord
Antwoord: B
Beide bijwerkingen gebruiken dezelfde sleutel, dus vervangt de tweede de eerste waarde en behoudt de map één sleutel-waardepaar. De waarde is 14, niet 19: put telt de nieuwe hoeveelheid niet op bij de vorige hoeveelheid. Voor optellen is een expressie nodig die leest en bijwerkt.

Vraag 2 van 10

Een voorraadmap waarvan de hoeveelheden niet null zijn, heeft geen sleutel "tray". Wat gebeurt er wanneer int n = map.get("tray"); wordt uitgevoerd?
  1. De instructie slaat 0 op in n en gaat verder.
  2. De instructie werpt ClassCastException op.
  3. De instructie voegt "tray" toe met waarde 0.
  4. De instructie werpt NullPointerException op.
Toon antwoordVerberg antwoord
Antwoord: D
Een get voor een ontbrekende sleutel geeft null terug en bij het toewijzen van dat resultaat aan een int probeert Java het via unboxing om te zetten. Null heeft geen primitieve gehele waarde, dus werpt Java NullPointerException op. De map levert geen nul en maakt geen hoeveelheid aan alleen omdat de doelvariabele numeriek is.

Vraag 3 van 10

Een lus moet elke apparaat-ID samen met de bijbehorende status uit een map lezen. Welke weergave biedt beide in één luselement?
  1. entrySet()
  2. keySet()
  3. values()
  4. map.keySet().toArray()
Toon antwoordVerberg antwoord
Antwoord: A
entrySet() biedt een sleutel-waardepaar met zowel een sleutel als de bijbehorende waarde. Een lus over sleutels kan de waarde met een extra zoekactie ophalen, maar het element uit de sleutelverzameling zelf biedt alleen de sleutel. De waardenweergave kan niet aangeven welke sleutel bij elke status hoort.

Vraag 4 van 10

Twee afzonderlijke objecten zijn gelijk volgens een correcte methode equals. Wat moeten hun hashcodes zijn?
  1. Verschillende gehele getallen.
  2. Hun aantallen velden.
  3. Hetzelfde gehele getal.
  4. Hun geheugenadressen.
Toon antwoordVerberg antwoord
Antwoord: C
Gelijke objecten moeten gelijke hashcodes teruggeven, zodat een hashcollectie ze volgens dezelfde vergelijkingsregel kan vinden. Verschillende hashcodes voor gelijke objecten schenden dat contract. De omgekeerde implicatie is onjuist: twee ongelijke objecten mogen een hashcode delen.

Vraag 5 van 10

Een map bevat "beam" → 9. Het programma voert Integer old = map.put("beam", 13); uit en daarna Integer removed = map.remove("beam");. Wat zijn old, removed en de uiteindelijke grootte?
  1. 13, 13 en 0.
  2. 9, 9 en 0.
  3. 9, 13 en 1.
  4. 9, 13 en 0.
Toon antwoordVerberg antwoord
Antwoord: D
De vervanging geeft de eerdere waarde 9 terug, terwijl het paar nu 13 opslaat. De verwijdering geeft daarom 13 terug en verwijdert het enige paar, zodat grootte 0 overblijft. Als je het eerste resultaat voor 13 aanziet, verwar je de waarde die put teruggeeft met de waarde die de methode opslaat.

Vraag 6 van 10

Een lus die een voorraad opschoont, doorloopt entrySet() en moet elk paar met waarde nul verwijderen. Hoe moet de lus het paar tijdens het doorlopen verwijderen?
  1. Gebruik de iterator van die doorloop en roep na next() de methode remove() aan.
  2. Gebruik een for-each-lus en roep voor elke sleutel met waarde nul remove() van de map aan.
  3. Gebruik een lus over paren en vervang elke waarde nul door null.
  4. Gebruik een lus over waarden en verwijder elke sleutel met waarde nul direct uit keySet().
Toon antwoordVerberg antwoord
Antwoord: A
De eigen verwijdermethode van de iterator stemt de verwijdering af op de huidige positie van de doorloop. Rechtstreeks verwijderen via de map of een gekoppelde weergave wijzigt de structuur die wordt doorlopen en kan ConcurrentModificationException veroorzaken. Een hoeveelheid door null vervangen zou het paar niet verwijderen.

Vraag 7 van 10

Een klasse Cell definieert equals(Cell other) en een hashCode op basis van velden. Afzonderlijke cellen met gelijke velden komen niet overeen als sleutels in een HashMap. Welke wijziging aan een methode verhelpt de gelijkheidsfout?
  1. Behoud equals(Cell other) en geef één constante hashcode terug.
  2. Overschrijf equals(Object other) met dezelfde veldvergelijkingen.
  3. Vervang de gelijkheidsmethode door een toString() op basis van velden.
  4. Voeg compareTo(Cell other) toe zonder de gelijkheidsmethoden te wijzigen.
Toon antwoordVerberg antwoord
Antwoord: B
Een map gebruikt equals(Object), dus is de methode met een Cell-parameter een overladen methode en blijft de overgeërfde gelijkheid op basis van identiteit gelden. Overschrijf de methode met een Object-parameter en gebruik overeenkomstige velden voor de hashcode. Alleen de hashcode wijzigen zorgt er niet voor dat de verkeerde gelijkheidsmethode bij het opzoeken wordt gebruikt.

Vraag 8 van 10

Een zoekactie in een HashMap bewaart een sleutel alleen wanneer de score daarvan strikt groter is dan de hoogste score tot dan toe. Twee sleutels hebben dezelfde hoogste score. Welk resultaat kan het programma garanderen?
  1. Een van de sleutels met die score, zonder gegarandeerde volgorde.
  2. De sleutel met die score die als eerste in de map is geplaatst.
  3. De sleutel met die score waarvan de naam alfabetisch als eerste komt.
  4. De sleutel met die score die als laatste in de map is geplaatst.
Toon antwoordVerberg antwoord
Antwoord: A
De zoekactie bewaart de sleutel met de hoogste score die als eerste wordt bezocht, omdat een gelijke score niet voldoet aan de test op strikt groter zijn. Een HashMap garandeert geen invoegvolgorde of alfabetische volgorde bij het doorlopen. Een voorspelbaar resultaat bij een gelijke stand vereist een expliciete regel of een daarvoor gekozen volgorde.

Vraag 9 van 10

Een map begint met "ink" → 4 en "paper" → 0. keys is een nieuwe ArrayList die uit de sleutelverzameling is gekopieerd. Het programma verwijdert "ink" uit keys, verwijdert "paper" via de sleutelverzameling van de map en verdubbelt daarna alle resterende mapwaarden. Wat blijft in de map over?
  1. Alleen "paper" → 0.
  2. Er blijven geen koppelingen over.
  3. Alleen "ink" → 8.
  4. Zowel "ink" → 8 als "paper" → 0.
Toon antwoordVerberg antwoord
Antwoord: C
De gekopieerde lijst staat op zichzelf, dus als je daar ink verwijdert, blijft de bijbehorende koppeling intact. De sleutelverzameling is gekoppeld aan de map, dus als je daar paper verwijdert, verdwijnt die koppeling. De overgebleven waarde voor ink verdubbelen geeft 8; als je de gekopieerde lijst ten onrechte als een gekoppelde weergave zou behandelen, zouden beide paren worden verwijderd.

Vraag 10 van 10

De gelijkheid en hashcodebepaling van Location gebruiken een veranderlijke coördinaat. Een sleutel wordt opgeslagen en daarna wordt de coördinaat gewijzigd terwijl de sleutel is opgeslagen; de koppeling wordt nu niet gevonden. Welke volgorde van bijwerken moet het ontwerp gebruiken om dit te voorkomen?
  1. Wijzig de coördinaat; zoek op met de nieuwe coördinaat; voeg opnieuw toe.
  2. Verwijder vóór de wijziging; wijzig de coördinaat; voeg opnieuw toe.
  3. Wijzig de coördinaat; vervang equals; zoek op met de oude coördinaat.
  4. Bewaar een tweede referentie; wijzig de coördinaat; zoek daarmee op.
Toon antwoordVerberg antwoord
Antwoord: B
De verwijdering moet plaatsvinden terwijl de sleutel nog de gelijkheids- en hashidentiteit heeft die bij het invoegen is gebruikt. Het programma kan de sleutel daarna wijzigen en met de nieuwe identiteit opnieuw invoegen. Na de wijziging met dezelfde referentie zoeken is geen oplossing: de gewijzigde hashcode kan nog steeds naar een andere plaats dan het opgeslagen paar leiden.
Set 2: Bouw tellingen op en vergelijk groepen10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Een frequentietabel in een map bevat "north" → 4, "south" → 2 en "west" → 3. Hoeveel verschillende sleutels bevat de map?
  1. 9
  2. 4
  3. 3
  4. 2
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een HashSet bevat al "cedar". Wat geeft een nieuwe add("cedar") terug?
  1. false
  2. true
  3. null
  4. De opgeslagen string.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een cursus moet elke deelnemer maar één keer vermelden, ook als dubbele inschrijvingsrecords binnenkomen. Welke regel voor de binnenste collectie past bij elke cursusgroep?
  1. Een lijst met deelnemer-ID’s.
  2. Een geheel aantal records.
  3. Eén deelnemer-ID als string.
  4. Een verzameling deelnemer-ID’s.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

De lus verwerkt "red", "gold", "red", "blue", "gold", "red" met counts.put(word, counts.getOrDefault(word, 0) + 1). Wat zijn het aantal voor red en de grootte van de map?
  1. Aantal red 1; grootte 3.
  2. Aantal red 3; grootte 3.
  3. Aantal red 3; grootte 6.
  4. Aantal red 6; grootte 3.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Binnen een groepeerlus wordt bij elke invoerwaarde groups.put(team, new ArrayList<>()); uitgevoerd, gevolgd door groups.get(team).add(name);. Een team ontvangt Omar, Pia en daarna Ren. Wat blijft onder dat team over?
  1. [Omar, Pia, Ren]
  2. [Ren]
  3. [Omar]
  4. Een lege lijst.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

A = {2, 5, 8, 11} en B = {5, 11, 14}. Een gekopieerde verzameling C begint met A en voert daarna C.removeAll(B) uit. Wat bevat C?
  1. {5, 11}
  2. {14}
  3. {2, 5, 8, 11, 14}
  4. {2, 8}
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Hetzelfde object Device is opgeslagen in een lijst en een ID-map. Het wordt uit de map opgehaald en daarna verandert het statusveld. Welke status toont de opgeslagen referentie in de lijst?
  1. De gewijzigde status van hetzelfde object.
  2. De oorspronkelijke status in een apart gekopieerd object.
  3. Null totdat het element in de lijst is vervangen.
  4. De gewijzigde status pas na een tweede put in de map.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

De reeks is [12, 7, 4, 12, 7]. Een lus stopt bij de eerste !seen.add(n). Welk getal wordt gemeld?
  1. 7
  2. 4
  3. 12
  4. Geen getal.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Eén ArrayList is opgeslagen onder zowel "Morning" als "Evening". Het programma voegt "Lee" toe via Morning, vervangt daarna de koppeling van Evening door een nieuwe lijst en voegt "Jo" toe via Evening. Wat zijn de uiteindelijke groepen?
  1. Morning [Lee]; Evening [Jo].
  2. Morning [Lee, Jo]; Evening [Lee, Jo].
  3. Morning []; Evening [Lee, Jo].
  4. Morning [Jo]; Evening [Jo].
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

A = {1, 3, 6} en B = {3, 6, 9}. C wordt gekopieerd uit A en voert retainAll(B) uit. D wordt gekopieerd uit B en voert removeAll(C) uit. Wat zijn D en het resultaat van A.containsAll(C)?
  1. D = {1}; het resultaat is true.
  2. D = {9}; het resultaat is false.
  3. D = {3, 6, 9}; het resultaat is false.
  4. D = {9}; het resultaat is true.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 3: Gebruik interfaces en sorteer gegevens10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Wat is in Set<String> codes = new HashSet<>(); het gedeclareerde type van codes?
  1. HashSet<String>
  2. String
  3. Collection<HashSet>
  4. Set<String>
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Wat betekent een positieve waarde die a.compareTo(b) teruggeeft?
  1. a komt vóór b in die volgorde.
  2. a en b hebben dezelfde sorteerrang.
  3. a komt na b in die volgorde.
  4. a heeft één groter numeriek veld.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een wijzigbare List<Integer> begint als [4, 8, 12]. De lijst voert remove(1) uit. Wat blijft over?
  1. [4, 12]
  2. [8, 12]
  3. [4, 8]
  4. [4, 8, 12]
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Wat is de natuurlijke gesorteerde volgorde van de strings "zebra", "Apron", "18", "3", "ant"?
  1. [“3”, “18”, “ant”, “Apron”, “zebra”]
  2. [“18”, “3”, “Apron”, “ant”, “zebra”]
  3. [“18”, “3”, “ant”, “Apron”, “zebra”]
  4. [“Apron”, “ant”, “zebra”, “18”, “3”]
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een methode die alleen leest, accepteert Collection<String>. Een aanroeper heeft Map<String, String> labels en wil dat de methode elke labelwaarde verwerkt. Wat moet worden doorgegeven?
  1. labels.values()
  2. labels
  3. labels.entrySet()
  4. labels.keySet().iterator()
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een prijsvergelijking geeft (int) (this.price - other.price) terug. Wat gaat er mis voor prijzen 6,8 en 6,3?
  1. De vergelijking plaatst 6,8 altijd vóór 6,3.
  2. De vergelijking overschrijdt het int-bereik.
  3. De vergelijking geeft nul terug voor ongelijke prijzen.
  4. De vergelijking verandert beide opgeslagen prijzen in gehele getallen.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Resultaten moeten worden gesorteerd op punten van hoog naar laag en daarna op naam van A tot Z. De primaire vergelijking is niet nul. Wat moet compareTo daarna doen?
  1. De namen vergelijken en dat resultaat teruggeven.
  2. Nul teruggeven om de invoervolgorde te behouden.
  3. Een omgekeerde naamvergelijking teruggeven.
  4. Het resultaat van de primaire vergelijking teruggeven.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een wijzigbare lijst bevat één veranderlijk object Ticket. Daarvan wordt een tweede ArrayList gekopieerd. Het programma wijzigt het label van het ticket via de kopie en maakt daarna de kopie leeg. Wat bevat de oorspronkelijke lijst?
  1. Een lege lijst zonder ticket.
  2. Hetzelfde ticket met het gewijzigde label.
  3. Een apart ticket met het oorspronkelijke label.
  4. Hetzelfde ticket met het oorspronkelijke label.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een klasse vergelijkt op aflopend niveau en daarna op oplopende code. De records zijn Delta 2, Beta 4, Alpha 2 en Echo 4. Welke volgorde ontstaat?
  1. Echo 4, Beta 4, Delta 2, Alpha 2.
  2. Alpha 2, Beta 4, Delta 2, Echo 4.
  3. Beta 4, Echo 4, Alpha 2, Delta 2.
  4. Alpha 2, Delta 2, Beta 4, Echo 4.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Reading.equals gebruikt station-ID en temperatuur, maar de natuurlijke vergelijking gebruikt alleen temperatuur. Een standaard TreeSet ontvangt A met 16, B met 16 en daarna C met 12. Wat zijn de grootte en de behouden ID’s?
  1. Grootte 2; ID’s C en A.
  2. Grootte 3; ID’s C, A en B.
  3. Grootte 2; ID’s C en B.
  4. Grootte 1; alleen ID C.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 4: Onderzoek het gedrag van collecties10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Een programma slaat de neerslag in millimeters op, op één plaats voor elk van de twaalf maanden. Het heeft een vast aantal plaatsen voor primitieve getallen nodig. Welke structuur past daar direct bij?
  1. Een Set<Double> met metingen.
  2. Een array double[12].
  3. Een Map<Double, String> met maanden.
  4. Een HashSet<Integer> met maandnummers.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een HashMap bevat de sleutel "pending" die expliciet aan null is gekoppeld. Wat geeft getOrDefault("pending", 20) terug?
  1. 20
  2. 0
  3. null
  4. Een exceptie door de zoekactie zelf.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Wat gebeurt er wanneer Set.of("draft", "final", "draft") wordt geëvalueerd?
  1. De aanroep werpt IllegalArgumentException op.
  2. De aanroep geeft een verzameling met twee elementen terug.
  3. De aanroep geeft een lijst met drie elementen terug.
  4. De aanroep werpt UnsupportedOperationException op.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een ledenindex gebruikt weergavenamen als sleutels. Twee verschillende leden met de naam "Ari Chen" worden ingevoegd en het eerste lid kan niet meer via die naam worden opgehaald. Welk ontwerp behoudt beide leden direct voor afzonderlijke zoekacties?
  1. Behoud de naam als sleutel, maar gebruik TreeMap.
  2. Behoud de naam als sleutel in een LinkedHashMap.
  3. Roep put opnieuw aan met dezelfde naam.
  4. Indexeer op de unieke ID van elk lid.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een veranderlijke lijst bevat op dit moment [10, 2, 7]. Wat is de inhoud na Collections.reverse(list)?
  1. [10, 7, 2]
  2. [2, 7, 10]
  3. [7, 10, 2]
  4. [7, 2, 10]
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een programma controleert herhaaldelijk of ID’s voorkomen in een grote ArrayList en heeft voor die controles geen posities nodig. Welke verandering voorkomt dat het volledige zoekwerk wordt herhaald?
  1. Bouw een nieuwe HashSet binnen de zoeklus.
  2. Kopieer de ArrayList één keer naar een LinkedList.
  3. Bouw één HashSet vóór de zoeklus.
  4. Sorteer voor elke zoekactie een nieuwe ArrayList.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een groepeermap heeft geen sleutel "Support". Het programma evalueert List<String> result = groups.getOrDefault("Support", new ArrayList<>()); en voegt daarna "Nia" toe aan result. Wat geeft een latere groups.get("Support") terug?
  1. null, omdat de standaardlijst nooit is ingevoegd.
  2. Een lijst met Nia, omdat de standaardlijst de groep werd.
  3. Een lege lijst, omdat de standaardlijst vóór de toevoeging is opgeslagen.
  4. Een exceptie, omdat een niet-opgeslagen standaardlijst niet kan worden gewijzigd.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

De gelijkheid van ScoreKey gebruikt team en punten; de natuurlijke vergelijking gebruikt alleen punten. Een standaard TreeMap krijgt de sleutel East-30 met waarde "old", West-30 met waarde "new" en daarna North-18 met waarde "low". Wat zijn de grootte en de waarde die met East-30 wordt gevonden?
  1. Grootte 3; de waarde is "old".
  2. Grootte 2; de waarde is "new".
  3. Grootte 2; de waarde is "old".
  4. Grootte 1; de waarde is "low".
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

A = {4, 7, 10} en B = {7, 10, 13}. Een kopie U voert eerst addAll(B) uit en daarna removeAll(A). Wat is U en is een van beide originelen veranderd?
  1. U = {4}; beide originelen zijn ongewijzigd.
  2. U = {4, 13}; alleen A is gewijzigd.
  3. U = {7, 10}; alleen B is gewijzigd.
  4. U = {13}; beide originelen zijn ongewijzigd.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een overzicht heeft cursussen in alfabetische volgorde nodig en voor elke cursus de unieke lid-ID’s in volgorde van eerste inschrijving. Welke buitenste en binnenste implementaties passen bij elkaar?
  1. TreeMap buiten; LinkedHashSet binnen.
  2. LinkedHashMap buiten; TreeSet binnen.
  3. TreeMap buiten; ArrayList binnen.
  4. HashMap buiten; LinkedHashSet binnen.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 5: Combineer opzoeken, groeperen en volgorde10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Wat bepaalt de gelijkheid tussen een ArrayList en een LinkedList met dezelfde elementwaarden?
  1. De waarden moeten in dezelfde volgorde voorkomen.
  2. De lijsten moeten dezelfde concrete klasse hebben.
  3. Alleen het aantal unieke waarden moet overeenkomen.
  4. De elementreferenties moeten allemaal identiek zijn.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een aanvankelijk lege map met totalen verwerkt reparaties 4,25, bezorging 2,50 en reparaties 3,75 met een optelling die nul als standaardwaarde gebruikt. Wat zijn de grootte en het totaal voor reparaties?
  1. Grootte 3; totaal reparaties 8,00.
  2. Grootte 2; totaal reparaties 3,75.
  3. Grootte 2; totaal reparaties 10,50.
  4. Grootte 2; totaal reparaties 8,00.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een zelfgeschreven klasse met correcte gelijkheid geeft voor elke instantie dezelfde hashcode terug. Wat gebeurt er met de juistheid en de opzoeksnelheid van een HashSet?
  1. Elke waarde gaat op in één element, waardoor zoeken sneller wordt.
  2. Verschillende ongelijke waarden blijven geldig, maar zoekacties kunnen trager worden.
  3. Verschillende waarden blijven geldig, met gegarandeerd zoeken in constante tijd.
  4. Elke invoeging mislukt bij het compileren omdat hashcodes worden herhaald.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een temperatuurklasse moet twee double-velden oplopend vergelijken zonder onterechte gelijke sorteerrangen door een expliciete typeconversie. Welke expressie moet worden teruggegeven?
  1. (int) (this.value - other.value)
  2. Double.compare(other.value, this.value)
  3. Double.compare(this.value, other.value)
  4. Integer.compare((int) this.value, (int) other.value)
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een map bevat twee verschillende sleutels die elk aan 6 zijn gekoppeld. Welk totaal ontstaat als je map.values() optelt?
  1. 12
  2. 6
  3. 2
  4. 1
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een catalogus bewaart dezelfde Item-objecten in een ID-index en een index van categorie naar lijst. De categorie van een artikel verandert van Cables naar Adapters. Als alleen het categorieveld verandert, blijft het artikel in de lijst Cables staan. Welke bijwerking houdt de indexen consistent?
  1. Vervang het in de ID-map; laat beide categorielijsten zoals ze zijn.
  2. Verander de ID-map in een TreeMap; laat beide categorielijsten zoals ze zijn.
  3. Verplaats de referentie tussen categorielijsten; behoud de ID-koppeling.
  4. Kopieer het artikel onder de oude categorie; verwijder de ID-koppeling.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een spelersklasse definieert gelijkheid op naam en score en vergelijkt op score aflopend en daarna op naam oplopend. Een standaard TreeSet ontvangt Mira 9, Axel 12, Mira 9 en Bo 9 als afzonderlijke objecten. Welke geordende verzameling ontstaat?
  1. Axel 12, Mira 9, Bo 9.
  2. Axel 12, Mira 9, Mira 9, Bo 9.
  3. Bo 9, Mira 9, Axel 12.
  4. Axel 12, Bo 9, Mira 9.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een programma heeft een lijst met toegestane waarden en een lijst met zoekwaarden. Beide groottes verdubbelen. Vergelijk herhaald volledig zoeken in de lijst met één HashSet van toegestane waarden opbouwen en daarin zoeken, bij geschikte hashing. Hoe groeit hun totale werk?
  1. Beide totalen kunnen verviervoudigen omdat beide invoeren twee keer zoveel waarden bevatten.
  2. Het werk voor zoeken in de lijst kan verviervoudigen; opbouwen en zoeken met een verzameling verdubbelt ongeveer.
  3. Het werk voor zoeken in de lijst verdubbelt ongeveer; opbouwen en zoeken met een verzameling blijft constant.
  4. Beide totalen blijven constant omdat elk één methodeaanroep per zoekactie gebruikt.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een map groepeert notities per project. Twee projecten moeten onafhankelijke lijsten, herhaalde notities en de volgorde van binnenkomst behouden. De bestaande code maakt één gedeelde ArrayList, plaatst die onder elke nieuwe sleutel en voegt notities toe via get. Welke volledige oplossing behoudt de vereisten?
  1. Behoud de gedeelde ArrayList, maar vervang elke get door getOrDefault met dezelfde lijst.
  2. Maak voor elke nieuwe sleutel een nieuwe ArrayList en voeg daarna toe via de opgeslagen referentie.
  3. Maak voor elke nieuwe sleutel een nieuwe HashSet en voeg daarna notities toe via de opgeslagen referentie.
  4. Maak bij elke invoerwaarde een nieuwe lege ArrayList voor het project en voeg daarna de huidige notitie toe.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een documentsysteem heeft unieke labels in volgorde van eerste voorkomen nodig, directe objectzoekacties via een unieke document-ID en een aparte geordende geschiedenis die herhaalde bezoeken bewaart. Welke structuren passen bij de drie behoeften?
  1. TreeSet voor labels; List voor zoeken op ID; HashSet voor geschiedenis.
  2. HashSet voor labels; Map voor zoeken op ID; TreeSet voor geschiedenis.
  3. LinkedHashSet voor labels; Set voor zoeken op ID; Map met document-ID als sleutel voor geschiedenis.
  4. LinkedHashSet voor labels; Map voor zoeken op ID; List voor geschiedenis.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Kom je niet uit je eigen opgave? Huiswerkhulp

Kernbegrippen

70 Kernbegrippen, elk met een definitie

A

Aanvullend sorteercriterium
Een aanvullend sorteercriterium is een tweede vergelijking die alleen wordt gebruikt wanneer eerdere vergelijkingsvelden gelijk zijn, zodat hun prioriteit in de totale volgorde behouden blijft.
Een filmvergelijking op eerst jaar en daarna titel raadpleegt titels alleen voor films die in hetzelfde jaar zijn uitgebracht.
Afkappen
Afkappen verwijdert het gedeelte achter de komma wanneer een waarde expliciet naar int wordt omgezet, waardoor een klein vergelijkingsverschil dat niet nul is, nul kan worden.
Als je het prijsverschil tussen 2,7 en 2,2 expliciet omzet naar int, krijg je een onterechte gelijke sorteerrang in plaats van een positieve vergelijking.
Array
Een array slaat een vast aantal elementen van één type op met indexen en kan primitieve waarden direct bevatten zonder wrappertypen als typeargumenten.
Een double[12] kan elke maand één plaats geven voor de neerslagmeting in millimeters.
Autoboxing
Autoboxing is de automatische omzetting door Java van een primitieve waarde naar het bijbehorende wrapperobject wanneer een object nodig is.
Als je de literal 12 in een map met Integer-waarden plaatst, zet Java dat getal automatisch via autoboxing om voor opslag.

C

Collectiekeuze
Een collectiekeuze stemt de vereiste posities, duplicaten, zoekacties op sleutel en volgorde af op een interface en een geschikte implementatie.
Een alfabetisch overzicht van aantallen en een geordende afspeellijst hebben verschillende structuren nodig omdat ze verschillende informatie bewaren.
Collectieweergave
Een collectieweergave maakt een deel van een andere structuur toegankelijk via een collectie-interface, waarbij wijzigingen zijn gekoppeld aan de onderliggende structuur.
Als je een product verwijdert via de sleutelverzameling van de voorraadmap, verwijder je het bijbehorende paar uit de map zelf.
Collection
Collection is de gemeenschappelijke Java-interface voor groepen elementen, die door List en Set wordt uitgebreid maar losstaat van de interface Map.
Een methode die alleen leest en woorden telt, kan een Collection<String> accepteren en een lijst of een verzameling doorlopen.
Comparable
Comparable is de Java-interface waarmee een klasse haar natuurlijke volgorde definieert door een getypeerde methode compareTo te implementeren.
Een ledenklasse kan Comparable<Member> implementeren zodat lijstsortering haar instanties op lengte kan ordenen.
Comparator
Een comparator is een object dat een vergelijkingsregel biedt die kan afwijken van de natuurlijke volgorde van een klasse, zoals een omgekeerde of hoofdletterongevoelige volgorde.
String.CASE_INSENSITIVE_ORDER sorteert een lijst zonder de hoofdletters en kleine letters in elke opgeslagen string te wijzigen.
compareTo
De methode compareTo geeft een negatief geheel getal, nul of een positief geheel getal terug om dit object respectievelijk vóór, op dezelfde sorteerrang als of na een ander object te plaatsen.
Een resultaat van -8 plaatst het linkerobject vóór het rechterobject, net zoals een resultaat van -1 dat zou doen.
Consistentie met equals
Consistentie met equals betekent dat de vergelijking precies dan nul teruggeeft wanneer de gelijkheidsmethode true teruggeeft, zodat beide regels dezelfde waarden herkennen.
Een tree-verzameling heeft een ledenvergelijking nodig die dezelfde identiteiten onderscheidt als de gelijkheidsregel van het lid.
Constante tijd
Constante tijd beschrijft werk dat ongeveer onafhankelijk blijft van het aantal elementen; basisbewerkingen met hashing hebben deze kosten gemiddeld bij geschikte hashing.
Eén positie van een ArrayList lezen vereist niet dat alle eerdere posities in die lijst worden doorzocht.

D

Deelverzameling
Een deelverzameling is een verzameling waarvan elk element ook in een andere verzameling voorkomt, die extra elementen mag bevatten; a.containsAll(b) test of b een deelverzameling van a is.
Een geselecteerde groep is een deelverzameling van een verzameling aanwezigen wanneer elke geselecteerde persoon op de lijst van dat evenement staat.
Diamantnotatie
Diamantnotatie gebruikt lege punthaken bij een constructor zodat Java de typeargumenten uit de omringende declaratie kan afleiden.
In HashMap<String, Integer> m = new HashMap<>(); voorkomt de diamantnotatie dat de twee typen worden herhaald.
Doorsnede
De doorsnede van twee verzamelingen bevat alleen de elementen die beide delen; retainAll verwijdert niet-gedeelde waarden uit de ontvangende verzameling.
Als je in een kopie van de verzameling van maandag alleen de namen van dinsdag behoudt, vind je de mensen die op beide dagen aanwezig waren.

E

Encapsulatie
Encapsulatie houdt gegevens binnen een klasse en biedt gecontroleerde methoden aan, zodat de klasse regels voor bijwerken en opzoeken kan handhaven.
Een bibliotheekklasse kan haar indexen privé houden zodat de methode addBook die samen bijwerkt in plaats van aanroepers ze te laten bewerken.

F

Frequentietabel
Een frequentietabel koppelt elk uniek element aan het aantal keren dat het voorkomt, vaak met mapsleutels voor elementen en gehele waarden voor aantallen.
Een map met woordtellingen onderscheidt het aantal verschillende woorden van het totale aantal woordvoorkomens.

G

Gedeclareerd type
Het gedeclareerde type van een variabele bepaalt welke methoden de compiler via die variabele toestaat, ook als het object extra methoden heeft.
Een ArrayList die in een List-variabele is opgeslagen, maakt ensureCapacity niet via die variabele beschikbaar.
Gedeelde referentie
Een gedeelde referentie laat twee variabelen of sleutel-waardeparen hetzelfde object bereiken, zodat een wijziging van dat object via beide referenties zichtbaar is.
Twee cursussleutels waaraan één lijstobject is toegewezen, tonen allebei een student die via slechts één van die sleutels is toegevoegd.
Gelijkheid op basis van identiteit
Gelijkheid op basis van identiteit beschouwt objecten alleen als gelijk wanneer ze dezelfde instantie zijn; dit is de gelijkheid die van Object wordt geërfd.
Zonder overschrijvingen komt een nieuw gemaakt punt niet overeen met een opgeslagen punt met identieke coördinaten.
Geneste collectie
Een geneste collectie slaat collecties op binnen een andere structuur, zodat buitenste sleutels en binnenste leden verschillende regels kunnen volgen.
Een gesorteerde cursusmap kan studentenlijsten in invoegvolgorde bevatten zonder de studenten zelf te sorteren.
getOrDefault
De methode getOrDefault geeft de waarde terug die aan een sleutel is gekoppeld, of de opgegeven standaardwaarde als er geen koppeling voor die sleutel bestaat.
Een ontbrekend aantal lezen met nul als standaardwaarde geeft 0 zonder een nieuw paar in de telmap te maken.
Groeperen
Groeperen brengt elementen met een gemeenschappelijke eigenschap onder één mapsleutel samen en gebruikt een lijst of verzameling als waarde waarin elke groep wordt opgeslagen.
Een cursussleutel kan naar een lijst met studenten leiden, terwijl een beginletter als sleutel naar bijpassende woorden kan leiden.

H

Hashcodecontract
Het hashcodecontract vereist dat objecten die volgens equals gelijk zijn, gelijke hashcodes teruggeven, maar staat hashbotsingen voor ongelijke objecten toe.
Coördinaatsleutels gebruiken dezelfde velden x en y in zowel hun gelijkheidstest als hun hashcodemethode.
HashMap
Een HashMap is een wijzigbare Java-map die unieke sleutels met bijbehorende waarden opslaat en geen bepaalde iteratievolgorde garandeert.
Een HashMap<String, Integer> kan het huidige aantal van een product opzoeken zonder een lijstpositie te gebruiken.
HashSet
Een HashSet is een wijzigbare Java-verzameling met basisbewerkingen in gemiddeld constante tijd bij geschikte hashing en zonder gegarandeerde iteratievolgorde.
Een HashSet<String> kan bijhouden welke namen al zijn verwerkt terwijl een programma een langere invoerreeks leest.
Herhaalde invoerwaarde
Een herhaalde invoerwaarde is een invoer waarvan al eerder een gelijke waarde is gezien; een verzameling met eerder geziene waarden detecteert die wanneer add false teruggeeft.
In de reeks 6, 9, 2, 9, 6 is de tweede 9 de eerste invoerwaarde die een eerdere waarde herhaalt.

I

Implementatie
Een implementatie is een concrete klasse die de bewerkingen van een interface biedt en het gedrag van het gemaakte object bepaalt.
HashMap en TreeMap implementeren allebei Map, maar geven verschillende garanties over de sleutelvolgorde.
Index
Een index is een map van een identificerende sleutel naar een object, waarmee je op die sleutel kunt zoeken zonder steeds een lijst met objecten te doorzoeken.
De ISBN-index van een bibliotheek kan hetzelfde boekobject teruggeven dat ook in de lijst met alle boeken voorkomt.
Inhoudelijke gelijkheid
Inhoudelijke gelijkheid behandelt afzonderlijke objecten als gelijk wanneer hun gekozen gegevens overeenkomen, met een passende overschrijving van equals(Object).
Twee afzonderlijk gemaakte coördinaatsleutels kunnen hetzelfde label vinden wanneer hun gelijkheidsmethode beide coördinaten vergelijkt.
Interface
Een interface declareert bewerkingen die implementerende klassen bieden, zodat een variabele of parameter kan aangeven welke functionaliteit nodig is.
Een methode die List<String> accepteert, kan een ArrayList of een LinkedList ontvangen zonder de signatuur te wijzigen.
Iteratievolgorde
Iteratievolgorde is de volgorde waarin een doorloop elementen of sleutel-waardeparen bezoekt; sommige implementaties garanderen een volgorde en andere niet.
Een zoekactie bij gelijke scores heeft een expliciete regel nodig als het resultaat onafhankelijk moet zijn van de volgorde waarin een HashMap wordt doorlopen.
Iterator
Een iterator houdt de voortgang bij tijdens het doorlopen van een collectie en biedt methoden om te controleren of er een volgend element is en dat op te halen.
Een lus die de voorraad opschoont, gebruikt hasNext(), next() en de remove() van de iterator om hoeveelheden van nul te verwijderen.

L

Lidmaatschap
Lidmaatschap beschrijft of een waarde tot een verzameling behoort, zoals contains dat test met de vergelijkingsregel van die verzameling.
Een programma dat gebruikersnamen controleert, test het lidmaatschap voordat het een nieuwe naam toevoegt aan de verzameling bezette namen.
Lineaire tijd
Lineaire tijd beschrijft werk dat evenredig met het aantal elementen kan groeien, bijvoorbeeld wanneer een zoekactie de hele collectie kan controleren.
Herhaalde lidmaatschapscontroles in een lange lijst kunnen telkens opnieuw vereisen dat dezelfde opgeslagen namen worden doorzocht.
LinkedHashMap
Een LinkedHashMap is een map waarvan de gewone vorm met invoegvolgorde sleutels in invoegvolgorde doorloopt en de gebruikelijke mapbewerkingen behoudt.
Als je een opgeslagen prijs vervangt, behoudt dat product zijn plaats in een LinkedHashMap met invoegvolgorde.
LinkedHashSet
Een LinkedHashSet slaat unieke elementen op en behoudt hun invoegvolgorde, inclusief de volgorde van eerste voorkomens bij het kopiëren uit een lijst.
Een lijst met labels die naar een LinkedHashSet wordt gekopieerd, verliest herhalingen maar behoudt de volgorde waarin labels voor het eerst voorkwamen.
List
Een List slaat elementen op in een reeks met indexen vanaf nul, staat duplicaten toe en vergelijkt gelijkheid aan de hand van de volledige elementvolgorde.
Een afspeellijst gebruikt lijstposities om twee voorkomens van hetzelfde nummer op verschillende plaatsen in de reeks te bewaren.
Logaritmische tijd
Logaritmische tijd beschrijft werk dat langzaam groeit met het aantal elementen, zoals bij de gegarandeerde kosten van eenvoudige zoekacties in tree-maps en tree-verzamelingen.
Een tree-map houdt sleutels gesorteerd zonder voor elke gewone zoekactie op sleutel alles te doorzoeken.
Lopend totaal
Een lopend totaal is een opgebouwd bedrag dat wordt bijgewerkt door elke nieuwe bijdrage op te tellen bij het al opgeslagen bedrag.
Een map met uitgaven leest het oude categorietotaal, telt het volgende bedrag erbij op en slaat het verhoogde resultaat op.

M

Map
Een Map koppelt unieke sleutels aan waarden en staat herhaalde waarden toe, terwijl elke sleutel tegelijk hoogstens één bijbehorende waarde heeft.
Twee producten kunnen beide aan prijs 3,50 zijn gekoppeld zonder de eis te schenden dat hun sleutels uniek zijn.
Map.Entry
Een Map.Entry vertegenwoordigt één sleutel-waardekoppeling en geeft tijdens het doorlopen van een map samen toegang tot de sleutel en de waarde.
Een lus over sleutel-waardeparen kan de naam en score van een speler weergeven zonder de score opnieuw op naam op te zoeken.

N

Natuurlijke volgorde
Een natuurlijke volgorde is de standaardvergelijking die een klasse biedt, zoals oplopende numerieke volgorde of stringvolgorde op basis van tekens.
Als je de strings "20" en "3" sorteert, komt "20" eerst omdat de eerste tekens hun volgorde bepalen.
Niet-wijzigbare collectie
Een niet-wijzigbare collectie wijst structurele wijzigingen en vervangingen via haar interface af, terwijl objecten die ze bevat nog steeds veranderlijk kunnen zijn.
Een lijst van List.of moet vóór het sorteren worden gekopieerd, maar een opgeslagen veranderlijk object wordt door die lijst niet bevroren.

O

Ondiepe kopie
Een ondiepe kopie maakt een aparte collectiestructuur met dezelfde elementreferenties in plaats van de opgeslagen objecten te kopiëren.
Een boek uit een gekopieerde lijst verwijderen laat de oorspronkelijke lijst intact, maar beide lijsten kunnen nog steeds naar hetzelfde boek verwijzen.
Opbouwkosten
Opbouwkosten zijn het werk dat nodig is om een ondersteunende structuur te bouwen voordat latere bewerkingen voordeel hebben van het gebruik ervan.
Een verzameling voor lidmaatschap moet je één keer vóór veel controles opbouwen, waarbij je de opbouw meetelt in het totale werk.
Opzoeken op sleutel
Opzoeken op sleutel vindt een waarde via een aparte identificator. Daardoor is een map bruikbaar wanneer herhaalde zoekacties anders objectvelden zouden moeten controleren.
Een map met productcodes beantwoordt prijsvragen direct, terwijl een lijst moet worden doorzocht op de overeenkomstige code.
Opzoektabel
Een opzoektabel koppelt codes of namen aan bijbehorende gegevens die een programma bij de verwerking van een andere taak ophaalt.
Een bestelcalculator leest productprijzen uit een tabel voordat de bijdrage van elk product wordt opgeteld.
Overladen methodevariant
Een overladen methodevariant is een methode met dezelfde naam als een andere methode maar met andere parameters, zodat Java een andere bewerking kan kiezen.
Voor een lijst met gehele getallen kiest remove(1) verwijdering op index, terwijl remove(Integer.valueOf(1)) verwijdering op waarde kiest.
Overloop bij gehele getallen
Overloop bij gehele getallen ontstaat wanneer een rekenkundig resultaat buiten het int-bereik valt en terugwikkelt, waardoor vergelijkingen op basis van aftrekken het verkeerde teken kunnen krijgen.
Extreme int-velden vergelijken met Integer.compare voorkomt de tekenomkering die aftrekken kan veroorzaken.

P

Parallelle lijsten
Parallelle lijsten slaan bijbehorende velden op overeenkomstige indexen in afzonderlijke lijsten op, waardoor de relatie afhangt van op elkaar afgestemde structurele wijzigingen.
Als je de naam van een persoon verwijdert zonder het nummer op dezelfde index te verwijderen, komen latere vermeldingen in het telefoonboek niet meer overeen.
Parameter van een interfacetype
Een parameter van een interfacetype accepteert objecten via de bewerkingen die een interface belooft, in plaats van één concrete implementatie te vereisen.
Een rapportagemethode kan Map<String, Integer> accepteren terwijl aanroepers opslag met een hashstructuur of boomstructuur kiezen.
putIfAbsent
De methode putIfAbsent slaat een waarde op wanneer een sleutel geen koppeling met een waarde anders dan null heeft en behoudt anders de waarde die al aan die sleutel is gekoppeld.
Voordat je een gegroepeerd element toevoegt, kan putIfAbsent ervoor zorgen dat de sleutel een lijst heeft zonder een bestaande lijst te vervangen.

S

Sleutel-waardepaar
Een sleutel-waardepaar koppelt een identificerende sleutel aan één bijbehorende waarde in een map, zoals een productcode aan een hoeveelheid.
In een voorraadmap koppelt het paar "pen" → 18 een productnaam aan het aantal dat momenteel beschikbaar is.
Sleutelnormalisatie
Sleutelnormalisatie past vóór het opslaan en opzoeken een consistente opschoonregel toe, zodat gelijkwaardige invoervormen dezelfde mapsleutel gebruiken.
Een woordteller kan tokens omzetten naar kleine letters en leestekens verwijderen voordat elk voorkomen aan de map wordt toegevoegd.
Stabiele sortering
Een stabiele sortering behoudt de onderlinge invoervolgorde van elementen die gelijk zijn volgens de vergelijking die voor die sortering wordt gebruikt.
Twee spelers die bij een vergelijking op alleen score gelijk zijn, behouden na een stabiele lijstsortering hun eerdere onderlinge volgorde.
Structurele wijziging
Een structurele wijziging verandert de verzameling sleutels van een map, bijvoorbeeld wanneer een nieuwe koppeling wordt toegevoegd of een bestaande wordt verwijderd.
De hoeveelheid vervangen voor een sleutel die al aanwezig is, verandert de waarde zonder de map structureel te wijzigen.

T

Tekenvolgorde
Tekenvolgorde vergelijkt strings op hun eerste verschillende UTF-16-code-eenheid; als de ene string een prefix van de andere is, komt de kortere string eerst.
In de voorbeelden "7", "Bee" en "ant" plaatst de natuurlijke stringvolgorde het cijfer vóór de letters.
Ter plaatse sorteren
Ter plaatse sorteren herschikt de meegegeven lijst zelf in plaats van een aparte gesorteerde lijst terug te geven die de aanroeper moet toewijzen.
Na Collections.sort(values) toont de bestaande lijstvariabele de elementen in hun nieuwe volgorde.
Transitiviteit
Transitiviteit vereist dat een ordening a vóór c plaatst wanneer die a vóór b en b vóór c plaatst, zodat vergelijkingen samenhangend blijven.
Velden vergelijken in een vaste volgorde van prioriteit voorkomt een cyclus waarin elk van drie objecten vóór een ander komt.
TreeMap
Een TreeMap houdt koppelingen geordend op hun sleutels en gebruikt sleutelvergelijking om tijdens opzoeken of vervangen een bestaande koppeling te herkennen.
Een alfabetisch overzicht van woordtellingen kan een tree-map gebruiken waarvan de kleinste sleutel beschikbaar is via firstKey().
TreeSet
Een TreeSet houdt elementen gesorteerd en gebruikt het vergelijkingsresultaat om te bepalen of een element al in de verzameling aanwezig is.
Een ledenvergelijking op alleen lengte laat twee verschillende leden met gelijke lengte om één positie in de verzameling concurreren.

U

Unboxing
Unboxing is de automatische omzetting door Java van een wrapperobject naar een primitieve waarde; een poging daartoe met null werpt een exceptie op.
Een ontbrekend Integer-zoekresultaat aan een int toewijzen mislukt omdat de teruggegeven null niet via unboxing kan worden omgezet.
Uniek element
Een uniek element is een waarde die volgens de vergelijkingsregel van de collectie als verschillend wordt beschouwd, ongeacht hoe vaak die waarde voorkomt.
Een frequentietabel in een map voor "sun rain sun" bevat twee unieke woordsleutels, maar registreert drie voorkomens.
Unieke identificator
Een unieke identificator onderscheidt elk object binnen de geïndexeerde gegevens en voorkomt dat afzonderlijke records om dezelfde mapsleutel concurreren.
Een lid-ID houdt twee personen met dezelfde weergavenaam in afzonderlijke paren van een ledenindex.

V

Veranderlijke sleutel
Een veranderlijke sleutel heeft gegevens die kunnen veranderen; als velden die voor gelijkheid of de hashcode worden gebruikt tijdens opslag veranderen, kan opzoeken in de map mislukken.
Een coördinaatsleutel is veiliger met final-velden dan met setters die de opgeslagen identiteit kunnen veranderen.
Vereniging
De vereniging van twee verzamelingen bevat elk element dat in minstens één van beide voorkomt; Java’s addAll vormt de vereniging door de ontvangende verzameling te wijzigen.
Als je de verzameling aanwezigen van maandag kopieert en die van dinsdag toevoegt, krijg je iedereen die op minstens één dag kwam.
Verschil van verzamelingen
Een verschil van verzamelingen bevat elementen uit de eerste verzameling die ontbreken in de tweede, zodat het omdraaien van de verzamelingen het resultaat kan veranderen.
Als je de aanwezigen van dinsdag uit een kopie van maandag verwijdert, vind je de aanwezigen van alleen maandag, niet die van alleen dinsdag.
Verzameling
Een verzameling is een collectie unieke elementen die lidmaatschapsbewerkingen biedt zonder de posities met index die een lijst biedt.
Een verzameling bezochte steden bewaart één element per stad, ook wanneer een reiziger meerdere keren terugkeert.

W

Wrapperklasse
Een wrapperklasse biedt een objecttype voor een primitieve waarde, zodat getallen en andere primitieve gegevens als typeargumenten voor collecties kunnen worden gebruikt.
Een voorraadmap gebruikt Integer als waardetype omdat int niet als generiek typeargument kan voorkomen.

Over deze les

Door StudeliFout melden

Maak je eigen Studiemateriaal

Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.

Aan de slag