Jonorakenne Javassa
Pyyhkäise näyttääksesi valikon
Aloitetaan Queue:lla. Kuvittele jono kaupassa alennusmyynnin aikana. Jonossa on 10 henkilöä; ensimmäinen henkilö on lähimpänä kaupan ovia ja kymmenes henkilö on kauimpana. Kun ensimmäinen henkilö astuu kauppaan, hän poistuu jonosta, jolloin koko jono siirtyy eteenpäin yhdellä henkilöllä. Java:n Queue toimii hyvin samanlaisella periaatteella.
Tällä tavoin voidaan toteuttaa erilaisia ohjelmia, joissa jonon logiikka on huolellisesti suunniteltu. Esimerkiksi suunnitelmien ja tehtävien hallintataulu.
Ensin tarkastellaan kuitenkin Queue:n perusmenetelmiä.
Queue on rajapinta, josta LinkedList-luokka perii ominaisuudet, ja tämä luokka on jo entuudestaan tuttu, joten käytämme tätä toteutusta.
Tällä tavoin käytetään rajapintaa olion tyyppinä, mutta olion toteutus on LinkedList, koska se on tämän olion tietty toteutus. (Muista, että et voi luoda olioita suoraan rajapinnasta).
Esimerkki:
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<>();
Tällä tavalla sovelluksesta voidaan tehdä erittäin joustava käyttämällä erilaisia toteutuksia samasta rajapinnasta.
Palataan kuitenkin takaisin Queue-rajapinnan käyttömenetelmiin.
Menetelmät
Joitakin keskeisiä Queue-rajapinnan menetelmiä ovat:
add(element): lisää jonoon alkion, heittää poikkeuksen jos operaatio ei ole mahdollinen;offer(element): lisää jonoon alkion, palauttaatruejos onnistuu taifalsemuuten.
Voit huomata, että nämä menetelmät tekevät pohjimmiltaan saman asian. Kuitenkin tärkein ero on offer-menetelmän turvallisuus. Jos alkiota ei voida lisätä oikein, offer-menetelmä ei heitä poikkeusta eikä pysäytä ohjelman suoritusta.
Tällä hetkellä tämä ominaisuus ei ole meille erityisen merkittävä, koska tavallisessa Queue-rakenteessa ei ole rajoituksia. On kuitenkin olemassa rakenne nimeltä BlockingQueue, jolla on rajoitus alkioiden määrässä; tällöin näillä menetelmillä on huomattava ero.
Tarkastellaan esimerkkiä:
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); } }
Kuten huomaat, kun käytetään add()-metodia ja yritetään lisätä alkio, joka ei mahdu jonoon, ohjelma heittää virheen ja suoritus päättyy odottamattomasti.
Kokeillaan samaa toimintoa, mutta turvallisemmalla menetelmällä — 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); } }
Kuten huomaat, nyt elementtiä ei lisätty jonoon, mutta myöskään poikkeusta ei heitetty. Voimme siis todeta, että käsittelimme virheen hallitusti.
Poikkeuksia voi käsitellä eri tavoin esimerkiksi try-catch-rakenteella, mutta käsittelemme sitä myöhemmin.
Poistomenetelmät
remove(): poistaa ja palauttaa jonon alussa olevan alkion, heittää poikkeuksen jos jono on tyhjä;poll(): poistaa ja palauttaa jonon alussa olevan alkion, palauttaanulljos jono on tyhjä.
Nämä menetelmät suorittavat täsmälleen saman toiminnon kuin jos ensimmäinen henkilö jonossa astuisi kauppaan ja poistuisi jonosta. Tässä toteutuu FIFO-periaate (First In, First Out). Toisin sanoen, ensimmäisenä jonoon lisätty alkio poistetaan ensimmäisenä.
Tässä näet myös näiden kahden menetelmän eron. poll()-menetelmää käytetään useammin kuin remove()-menetelmää, koska se on turvallisempi eikä heitä poikkeuksia.
Tarkastellaanpa esimerkkiä:
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); } }
Kuten huomaat, ohjelma heittää NoSuchElementException-poikkeuksen, koska yritämme poistaa alkion tyhjästä jonosta.
Tällaisen poikkeuksen välttämiseksi on parempi käyttää poll()-metodia:
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); } }
Nyt olemme poistaneet alkion jonosta turvallisesti, eikä poikkeusta heitetty, kun yritimme poistaa alkion tyhjästä listasta.
poll()-metodin palauttamaa null-ominaisuutta voidaan hyödyntää esimerkiksi while()-silmukassa.
Tarkastellaan esimerkkiä:
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); } }
Tällä tavalla kaikki jonon alkiot voidaan poistaa silmukkaa käyttäen.
Muista, että ensimmäinen jonoon lisätty alkio on se, joka poistetaan ensimmäisenä! Esimerkiksi yllä olevassa esimerkissä alkio, jonka data on "One", poistettiin ensin.
Alla havainnollistetaan FIFO-periaatetta:
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); } }
Voimme siirtyä menetelmiin, jotka palauttavat ensimmäisen ja viimeisen alkion:
element(): palauttaa, mutta ei poista, jonon alusta alkion, heittäen poikkeuksen jos jono on tyhjä;peek(): palauttaa, mutta ei poista, jonon alusta alkion, palauttaennull, jos jono on tyhjä.
peek()-menetelmän käyttö on luotettavampi ja turvallisempi tapa, sillä se auttaa välttämään mahdolliset poikkeukset.
Tarkastellaan esimerkkiä käytöstä:
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); } }
Voit yhdistää tämän menetelmän muihin jonon menetelmiin.
Jos sinulla on jono, jossa on viisi alkiota ja sinun täytyy poistaa kaikki alkiot neljänteen asti (mukaan lukien), tarkastellaan tällaisen operaation toteutusta:
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); } }
Käytit silmukkaa, jonka ehto perustui peek()-metodiin.
Voit optimoida tämän silmukan merkittävästi käyttämällä contains()-metodia. Tämä metodi palauttaa arvon true, jos määritetty alkio on jonossa, ja false, jos se ei ole.
Parannetaan yllä olevaa koodia:
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); } }
Tässä asetetaan yksi ehto while -silmukalle. Onnistuttiin poistamaan kaikki alkiot mukaan lukien "Four"-alkio.
1. Mikä on Queue Javassa?
2. Mikä rajapinta edustaa Queuea Java Collections Frameworkissa?
3. Mikä on offer()-metodin tarkoitus Queue-rajapinnassa?
4. Mitä poll()-metodi tekee Queue-rajapinnassa?
5. Mikä luokka Javan java.util.concurrent-paketissa edustaa rajattua estävää jonoa?
6. Mitä tapahtuu, jos yrität lisätä alkion täyteen jonoon käyttämällä add()-metodia?
Kiitos palautteestasi!
Kysy tekoälyä
Kysy tekoälyä
Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme