Java Collections beheersen: Uitgebreide Gids voor Efficiënte Datastructuren
Waarom het Collections Framework?
Voor Java 2 bood Java ad-hoc klassen zoals Dictionary, Vector, Stack en Properties om groepen objecten op te slaan en te manipuleren. Hoewel deze klassen nuttig waren, miste een centraal, verenigend thema. De manier waarop je Vector gebruikte, verschilde van hoe je Properties gebruikte.
Het collections framework is ontworpen om verschillende doelen te bereiken:
- Het framework moest hoge prestaties leveren. De implementaties voor de fundamentele collecties (dynamische arrays, gelinkte lijsten, bomen en hashtables) moesten zeer efficiënt zijn.
- Het framework moest verschillende typen collecties op een vergelijkbare manier laten werken en met een hoge graad van interoperabiliteit.
- Het framework moest een collectie eenvoudig kunnen uitbreiden en/of aanpassen.
Daarvoor is het hele collections framework ontworpen rond een set standaardinterfaces. Verschillende standaardimplementaties zoals LinkedList, HashSet en TreeSet van deze interfaces worden geboden die je als-zodanig kunt gebruiken, en je kunt ook je eigen collectie implementeren als je kiest.
Een collections framework is een geünificeerde architectuur voor het representeren en manipuleren van collecties. Alle collections frameworks bevatten:
- Interfaces – Dit zijn abstracte datatypen die collecties representeren. Interfaces stellen collecties in staat om onafhankelijk van de details van hun representatie te worden gemanipuleerd. In object-georiënteerde talen vormen interfaces doorgaans een hiërarchie.
- Implementaties (Classes) – Dit zijn de concrete implementaties van de collectie-interfaces. In essentie zijn dit herbruikbare datastructuren.
- Algoritmes – Dit zijn methodes die nuttige berekeningen uitvoeren, zoals zoeken en sorteren, op objecten die collectie-interfaces implementeren. De algoritmes worden gezegd polymorf te zijn: dezelfde methode kan op veel verschillende implementaties van de geschikte collectie-interface worden gebruikt.
Naast collecties definieert het framework verschillende map-interfaces en -klassen. Maps slaan sleutel/waarde-paren op. Hoewel maps niet collecties zijn in de strikte zin van het woord, zijn ze volledig geïntegreerd met collecties.
De Collectie-Interfaces
Het collections framework definieert verschillende interfaces. Deze sectie geeft een overzicht van elke interface:
| Nr. | Interface & Beschrijving |
|---|---|
| 1 | The Collection Interface Staat je toe om met groepen objecten te werken; het staat aan de top van de collectie-hiërarchie. |
| 2 | The List Interface Breidt Collection uit en een instantie van List slaat een geordende collectie elementen op. |
| 3 | The Set Breidt Collection uit om sets te behandelen, die unieke elementen moeten bevatten. |
| 4 | The SortedSet Breidt Set uit om gesorteerde sets te behandelen. |
| 5 | The Map Koppelt unieke sleutels aan waarden. |
| 6 | The Map.Entry Beschrijft een element (een sleutel/waarde-paar) in een map. Dit is een inner class van Map. |
| 7 | The SortedMap Breidt Map uit zodat de sleutels in oplopende volgorde worden bewaard. |
| 8 | The Enumeration Dit is een legacy-interface die de methodes definieert waarmee je elementen in een verzameling objecten kunt enumereren (één voor één ophalen). Deze legacy-interface is vervangen door Iterator. |
De Collectie-Klassen
Java biedt een set standaard collectie-klassen die Collectie-interfaces implementeren. Sommige klassen bieden volledige implementaties die als-zodanig gebruikt kunnen worden, andere zijn abstracte klassen die skeletale implementaties bieden als startpunt voor concrete collecties.
De standaard collectie-klassen samengevat:
| Nr. | Klasse & Beschrijving |
|---|---|
| 1 | AbstractCollection Implementeert het meeste van de Collection-interface. |
| 2 | AbstractList Breidt AbstractCollection uit en implementeert het meeste van de List-interface. |
| 3 | AbstractSequentialList Breidt AbstractList uit voor gebruik door een collectie die sequentiële toegang gebruikt in plaats van willekeurige toegang. |
| 4 | LinkedList Implementeert een gelinkte lijst door AbstractSequentialList uit te breiden. |
| 5 | ArrayList Implementeert een dynamische array door AbstractList uit te breiden. |
| 6 | AbstractSet Breidt AbstractCollection uit en implementeert het meeste van de Set-interface. |
| 7 | HashSet Breidt AbstractSet uit voor gebruik met een hashtabel. |
| 8 | LinkedHashSet Breidt HashSet uit om iteratie in invoegvolgorde toe te staan. |
| 9 | TreeSet Implementeert een set opgeslagen in een boom. Breidt AbstractSet uit. |
| 10 | AbstractMap Implementeert het meeste van de Map-interface. |
| 11 | HashMap Breidt AbstractMap uit om een hashtabel te gebruiken. |
| 12 | TreeMap Breidt AbstractMap uit om een boom te gebruiken. |
| 13 | WeakHashMap Breidt AbstractMap uit om een hashtabel met zwakke sleutels te gebruiken. |
| 14 | LinkedHashMap Breidt HashMap uit om iteratie in invoegvolgorde toe te staan. |
| 15 | IdentityHashMap Breidt AbstractMap uit en gebruikt referentiegelijkheid bij het vergelijken van documenten. |
De AbstractCollection, AbstractSet, AbstractList, AbstractSequentialList en AbstractMap klassen bieden skeletale implementaties van de kerncollectie-interfaces, om de inspanning te minimaliseren die nodig is om ze te implementeren.
De volgende legacy-klassen gedefinieerd door java.util zijn besproken in het vorige hoofdstuk:
| Nr. | Klasse & Beschrijving |
|---|---|
| 1 | Vector Implementeert een dynamische array. Vergelijkbaar met ArrayList, maar met enkele verschillen. |
| 2 | Stack Stack is een subklasse van Vector die een standaard last-in, first-out stack implementeert. |
| 3 | Dictionary Dictionary is een abstracte klasse die een sleutel/waarde opslagplaats vertegenwoordigt en werkt als Map. |
| 4 | Hashtable Hashtable was onderdeel van de oorspronkelijke java.util en is een concrete implementatie van een Dictionary. |
| 5 | Properties Properties is een subklasse van Hashtable. Wordt gebruikt om lijsten van waarden te onderhouden waar de sleutel een String is en de waarde ook een String. |
| 6 | BitSet Een BitSet-klasse creëert een speciaal type array dat bitwaarden bevat. Deze array kan in grootte toenemen zoals nodig. |
De Collectie-Algoritmes
Het collections framework definieert verschillende algoritmes die op collecties en maps toegepast kunnen worden. Deze algoritmes zijn gedefinieerd als statische methodes binnen de Collections-klasse.
Verschillende methodes kunnen een ClassCastException gooien (wanne er geprobeerd wordt incompatibele typen te vergelijken) of een UnsupportedOperationException (wanne er geprobeerd wordt een onveranderlijke collectie te wijzigen).
Collections definieert drie statische variabelen: EMPTY_SET, EMPTY_LIST en EMPTY_MAP. Allemaal zijn immutable.
Hoe een Iterator te Gebruiken?
Vaak wil je door de elementen in een collectie itereren. Bijvoorbeeld, om elk element weer te geven.
De makkelijkste manier is een iterator te gebruiken, een object dat de Iterator of ListIterator-interface implementeert.
Iterator stelt je in staat om door een collectie te cyclen, elementen op te halen of te verwijderen. ListIterator breidt Iterator uit om bidirectionele traversie van een lijst en wijziging van elementen toe te staan.
Hoe een Comparator te Gebruiken?
Zowel TreeSet als TreeMap slaan elementen op in gesorteerde volgorde. Maar het is de comparator die precies definieert wat gesorteerde volgorde betekent.
Deze interface laat ons een gegeven collectie op elk aantal manieren sorteren. Ook kan deze interface gebruikt worden om instanties van elke klasse te sorteren (zelfs klassen die we niet kunnen wijzigen).
Samenvatting
Het Java collections framework geeft de programmeur toegang tot kant-en-klaar datastructuren alsook algoritmes voor het manipuleren ervan.
Een collectie is een object dat referenties naar andere objecten kan bevatten. De collectie-interfaces declareren de operaties die op elk type collectie uitgevoerd kunnen worden.
De klassen en interfaces van het collections framework zitten in pakket java.util.
Java
- C# Collections Beheersen: Een Praktische Tutorial met Real-World Voorbeelden
- Java-operators beheersen: typen, syntax en praktische voorbeelden
- Java-commentaar: typen, gebruik en best practices
- Java Enhanced For-lus beheersen: syntax, voorbeelden en best practices
- Java Strings beheersen: aanmaken, methodes en best practices
- Java interfaces meesteren: concepten, implementatie en best practices
- Java anonieme inner classes meesteren: definitie, syntax en praktische voorbeelden
- Java Try-with-resources meesteren: automatische resource management uitgelegd
- Java Annotaties uitgelegd: typen, plaatsing en praktische voorbeelden
- Java Assertions: een praktische gids voor bugdetectie en codebetrouwbaarheid
- Java Collections beheersen: Uitgebreide Gids voor Efficiënte Datastructuren