Queue-Gegevensstructuur in Java
Veeg om het menu te tonen
Laten we beginnen met een Queue. Stel je een wachtrij in een winkel voor tijdens een uitverkoop. Er staan 10 mensen; de eerste persoon staat dichter bij de winkeldeuren dan de anderen, en de 10e persoon staat het verst weg. Wanneer de eerste persoon de winkel binnenkomt, verlaat deze de wachtrij, waardoor de hele rij één persoon naar voren schuift. De Java Queue werkt volgens een zeer vergelijkbaar principe.
Op deze manier kun je verschillende programma's implementeren waarbij de wachtrijlogica goed doordacht is. Bijvoorbeeld het implementeren van een bord met plannen en taken.
Maar eerst bekijken we de basis methoden voor het werken met een Queue.
Queue is een interface waarvan de LinkedList klasse erft, waarmee je al bekend bent, dus we zullen deze implementatie gebruiken.
Op deze manier gebruik je de interface als het type van het object, maar de implementatie van het object zal LinkedList zijn omdat dit een specifieke implementatie van dit object is. (Onthoud dat je geen objecten kunt maken op basis van een interface).
Voorbeeld:
Example.java
1234// `LinkedList` as implementation of the `List` interface: List<T> list = new LinkedList<>(); // `LinkedList` as implementation of the `Queue` interface: Queue<T> queue = new LinkedList<>();
Op deze manier kan de applicatie zeer flexibel worden gemaakt door verschillende implementaties van dezelfde interface te gebruiken.
Laten we echter teruggaan naar de methoden voor het werken met Queue.
Methoden
Enkele belangrijke methoden van de Queue-interface zijn:
add(element): voegt een element toe aan de queue, gooit een uitzondering als de bewerking niet mogelijk is;offer(element): voegt een element toe aan de queue en retourneerttruebij succes offalseanders.
Het valt op dat deze methoden in wezen hetzelfde doen. Het belangrijkste verschil is echter de veiligheid van de offer-methode. In het geval van een onjuist toegevoegd element zal de offer-methode geen uitzondering gooien en de uitvoering van het programma niet onderbreken.
Op dit moment is deze eigenschap voor ons niet bijzonder relevant, omdat een gewone Queue niet beperkt is. Er bestaat echter een structuur genaamd BlockingQueue, die een beperking op het aantal elementen heeft; in dat geval zal er een merkbaar verschil zijn tussen deze methoden.
Laten we een voorbeeld bekijken:
Main.java
1234567891011121314package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.add("One"); queue.add("Two"); queue.add("Three"); System.out.println("Queue: " + queue); } }
Zoals je kunt zien, wanneer de methode add() wordt gebruikt en geprobeerd wordt een element toe te voegen dat niet in de wachtrij past, geeft het programma een foutmelding en wordt de uitvoering onverwacht beëindigd.
Laten we dezelfde bewerking proberen, maar nu met een veiligere methode — offer():
Main.java
1234567891011121314package com.example; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class Main { public static void main(String[] args) { BlockingQueue<String> queue = new LinkedBlockingQueue<>(2); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); } }
Zoals je kunt zien, is het element niet aan de wachtrij toegevoegd, maar is er ook geen uitzondering opgetreden. We kunnen dus stellen dat we de fout op een nette manier hebben afgehandeld.
Je kunt uitzonderingen ook op een andere manier afhandelen met een structuur zoals try-catch, maar dat bespreken we later.
Verwijderingsmethoden
remove(): verwijdert en retourneert het element aan het begin van de wachtrij en gooit een uitzondering als de wachtrij leeg is;poll(): verwijdert en retourneert het element aan het begin van de wachtrij en retourneertnullals de wachtrij leeg is.
Deze methoden voeren precies de functie uit alsof de eerste persoon in de wachtrij de winkel binnengaat en de wachtrij verlaat. Hier komt het FIFO-principe (First In, First Out) aan bod. Met andere woorden, het element dat als eerste aan de wachtrij is toegevoegd, zal als eerste worden verwijderd.
Hier kun je ook het verschil tussen deze twee methoden zien. De poll()-methode wordt vaker gebruikt dan de remove()-methode omdat deze veiliger is en geen uitzonderingen gooit.
Laten we een voorbeeld bekijken:
Main.java
123456789101112131415package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.remove(); queue.remove(); System.out.println("Queue after removal operation: " + queue); } }
Zoals je kunt zien, geeft het programma een NoSuchElementException omdat we proberen een element uit een lege wachtrij te verwijderen.
Om een dergelijke uitzondering te voorkomen, is het beter om de methode poll() te gebruiken:
Main.java
123456789101112131415package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); System.out.println("Queue: " + queue); queue.poll(); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Nu hebben we veilig een element uit de wachtrij verwijderd, en er is geen uitzondering opgetreden toen we probeerden een element uit een lege lijst te verwijderen.
De eigenschap dat poll() null retourneert, kan bijvoorbeeld worden gebruikt in een while()-lus.
Laten we naar een voorbeeld kijken:
Main.java
1234567891011121314151617181920package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.poll() != null) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }
Op deze manier kunnen alle elementen uit de wachtrij worden verwijderd met behulp van een lus.
Onthoud dat het eerste element dat in de wachtrij is geplaatst, het element is dat wordt verwijderd! In het bovenstaande voorbeeld werd bijvoorbeeld het element met de data "One" als eerste verwijderd.
Het FIFO-principe wordt hieronder gedemonstreerd:
Main.java
123456789101112131415161718package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
We kunnen nu verdergaan met de methoden die het eerste en laatste element teruggeven:
element(): geeft het element aan het begin van de wachtrij terug, maar verwijdert het niet, en gooit een uitzondering als de wachtrij leeg is;peek(): geeft het element aan het begin van de wachtrij terug, maar verwijdert het niet, en geeftnullterug als de wachtrij leeg is.
Het gebruik van de peek()-methode is een betrouwbaardere en veiligere aanpak, omdat het helpt om mogelijke uitzonderingen te voorkomen.
Hier volgt een voorbeeld van het gebruik:
Main.java
12345678910111213141516package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); System.out.println("Queue: " + queue); System.out.println("The first element in the queue: " + queue.peek()); System.out.println("Queue after the `peek()` method: " + queue); } }
Je kunt deze methode combineren met andere wachtrijmethoden.
Als je een wachtrij met vijf elementen hebt en je moet alle elementen tot en met het vierde verwijderen, laten we dan de implementatie van zo'n bewerking bekijken:
Main.java
123456789101112131415161718192021package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (!queue.peek().equals("Four")) { queue.poll(); } queue.poll(); System.out.println("Queue after removal operation: " + queue); } }
Er is een lus gebruikt met een conditie gebaseerd op de methode peek().
Deze lus kan aanzienlijk geoptimaliseerd worden door de methode contains() te gebruiken. Deze methode retourneert true als het gespecificeerde element aanwezig is in de queue en false als dat niet het geval is.
Hier volgt een verbetering van bovenstaande code:
Main.java
1234567891011121314151617181920package com.example; import java.util.LinkedList; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.offer("One"); queue.offer("Two"); queue.offer("Three"); queue.offer("Four"); queue.offer("Five"); System.out.println("Queue: " + queue); while (queue.contains("Four")) { queue.poll(); } System.out.println("Queue after removal operation: " + queue); } }
Hier stellen we één enkele voorwaarde in voor de while lus. We zijn erin geslaagd om alle elementen tot en met het element "Four" te verwijderen.
1. Wat is een Queue in Java?
2. Welke interface vertegenwoordigt een Queue in het Java Collections Framework?
3. Wat is het doel van de methode offer() in de interface Queue?
4. Wat doet de methode poll() in de interface Queue?
5. Welke klasse in het pakket java.util.concurrent van Java vertegenwoordigt een begrensde blokkerende queue?
6. Wat gebeurt er als je probeert een element toe te voegen aan een volle wachtrij met de methode add()?
Bedankt voor je feedback!
Vraag AI
Vraag AI
Vraag wat u wilt of probeer een van de voorgestelde vragen om onze chat te starten.