Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Oppiskele Jonorakenne Javassa | Edistyneet Tietorakenteet Javassa
Practice
Projects
Quizzes & Challenges
Quizzes
Challenges
/
Java-tietorakenteet

bookJonorakenne Javassa

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 yhden henkilön verran. Java:n Queue toimii hyvin samanlaisella periaatteella.

Tällä tavoin voit toteuttaa erilaisia ohjelmia, joissa jonon logiikka on tarkkaan mietitty. Esimerkiksi suunnitelmien ja tehtävien hallintataulu.

Mutta ensin tarkastellaan perusmenetelmiä, joilla työskennellään Queue:n kanssa.

Queue on rajapinta, josta LinkedList-luokka perii, ja johon olet jo tutustunut, joten käytämme tätä toteutusta.

Tällä tavoin käytät rajapintaa olion tyyppinä, mutta olion toteutus on LinkedList, koska se on tämän olion tietty toteutus. (Muista, että et voi luoda olioita pelkän rajapinnan perusteella).

Esimerkki:

Example.java

Example.java

copy
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, palauttaa true jos onnistuu tai false muuten.

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 kuitenkaan ole meille kovin merkittävä, koska tavallinen Queue ei ole rajoitettu. 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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
1234567891011121314
package 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ä virhe käsiteltiin hallitusti.

Poikkeuksia voi käsitellä eri tavoin käyttämällä esimerkiksi try-catch-rakennetta, 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, palauttaa null jos 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 on ensimmäinen, joka poistetaan.

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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
123456789101112131415
package 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 syntynyt, kun yritimme poistaa alkion tyhjästä listasta.

poll()-metodin ominaisuutta, jossa palautetaan null, voidaan hyödyntää esimerkiksi while()-silmukassa.

Tarkastellaan esimerkkiä:

Main.java

Main.java

copy
1234567891011121314151617181920
package 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 silmukan avulla.

Muista, että ensimmäinen jonoon lisätty alkio on se, joka poistetaan! Esimerkiksi yllä olevassa esimerkissä alkio, jonka data on "One", poistettiin ensimmäisenä.

Alla havainnollistetaan FIFO-periaatetta:

Main.java

Main.java

copy
123456789101112131415161718
package 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 jonon 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, palauttaen null jos jono on tyhjä.

peek()-menetelmän käyttö on luotettavampi ja turvallisempi lähestymistapa, sillä se auttaa välttämään mahdolliset poikkeukset.

Tarkastellaan esimerkkiä käytöstä:

Main.java

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
123456789101112131415161718192021
package 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.

Tätä silmukkaa voidaan optimoida merkittävästi käyttämällä contains()-metodia. Tämä metodi palauttaa true, jos määritetty alkio on jonossa, ja false, jos ei ole.

Parannetaan yllä olevaa koodia:

Main.java

Main.java

copy
1234567891011121314151617181920
package 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ä asetamme yhden ehdon while -silmukalle. Onnistuneesti poistimme kaikki alkiot mukaan lukien "Four"-alkion.

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 rajoitettua estävää jonoa?

6. Mitä tapahtuu, jos yrität lisätä alkion täyteen jonoon käyttämällä add()-metodia?

question mark

Mikä on Queue Javassa?

Select the correct answer

question mark

Mikä rajapinta edustaa Queuea Java Collections Frameworkissa?

Select the correct answer

question mark

Mikä on offer()-metodin tarkoitus Queue-rajapinnassa?

Select the correct answer

question mark

Mitä poll()-metodi tekee Queue-rajapinnassa?

Select the correct answer

question mark

Mikä luokka Javan java.util.concurrent -paketissa edustaa rajoitettua estävää jonoa?

Select the correct answer

question mark

Mitä tapahtuu, jos yrität lisätä alkion täyteen jonoon käyttämällä add()-metodia?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 1

Kysy tekoälyä

expand

Kysy tekoälyä

ChatGPT

Kysy mitä tahansa tai kokeile jotakin ehdotetuista kysymyksistä aloittaaksesi keskustelumme

Suggested prompts:

Can you explain more about the difference between add() and offer() methods?

How does the FIFO principle work in a real-world queue?

What are some practical uses of the Queue interface in Java?

bookJonorakenne 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 yhden henkilön verran. Java:n Queue toimii hyvin samanlaisella periaatteella.

Tällä tavoin voit toteuttaa erilaisia ohjelmia, joissa jonon logiikka on tarkkaan mietitty. Esimerkiksi suunnitelmien ja tehtävien hallintataulu.

Mutta ensin tarkastellaan perusmenetelmiä, joilla työskennellään Queue:n kanssa.

Queue on rajapinta, josta LinkedList-luokka perii, ja johon olet jo tutustunut, joten käytämme tätä toteutusta.

Tällä tavoin käytät rajapintaa olion tyyppinä, mutta olion toteutus on LinkedList, koska se on tämän olion tietty toteutus. (Muista, että et voi luoda olioita pelkän rajapinnan perusteella).

Esimerkki:

Example.java

Example.java

copy
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, palauttaa true jos onnistuu tai false muuten.

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 kuitenkaan ole meille kovin merkittävä, koska tavallinen Queue ei ole rajoitettu. 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

Main.java

copy
1234567891011121314
package 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

Main.java

copy
1234567891011121314
package 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ä virhe käsiteltiin hallitusti.

Poikkeuksia voi käsitellä eri tavoin käyttämällä esimerkiksi try-catch-rakennetta, 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, palauttaa null jos 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 on ensimmäinen, joka poistetaan.

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

Main.java

copy
123456789101112131415
package 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

Main.java

copy
123456789101112131415
package 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 syntynyt, kun yritimme poistaa alkion tyhjästä listasta.

poll()-metodin ominaisuutta, jossa palautetaan null, voidaan hyödyntää esimerkiksi while()-silmukassa.

Tarkastellaan esimerkkiä:

Main.java

Main.java

copy
1234567891011121314151617181920
package 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 silmukan avulla.

Muista, että ensimmäinen jonoon lisätty alkio on se, joka poistetaan! Esimerkiksi yllä olevassa esimerkissä alkio, jonka data on "One", poistettiin ensimmäisenä.

Alla havainnollistetaan FIFO-periaatetta:

Main.java

Main.java

copy
123456789101112131415161718
package 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 jonon 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, palauttaen null jos jono on tyhjä.

peek()-menetelmän käyttö on luotettavampi ja turvallisempi lähestymistapa, sillä se auttaa välttämään mahdolliset poikkeukset.

Tarkastellaan esimerkkiä käytöstä:

Main.java

Main.java

copy
12345678910111213141516
package 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

Main.java

copy
123456789101112131415161718192021
package 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.

Tätä silmukkaa voidaan optimoida merkittävästi käyttämällä contains()-metodia. Tämä metodi palauttaa true, jos määritetty alkio on jonossa, ja false, jos ei ole.

Parannetaan yllä olevaa koodia:

Main.java

Main.java

copy
1234567891011121314151617181920
package 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ä asetamme yhden ehdon while -silmukalle. Onnistuneesti poistimme kaikki alkiot mukaan lukien "Four"-alkion.

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 rajoitettua estävää jonoa?

6. Mitä tapahtuu, jos yrität lisätä alkion täyteen jonoon käyttämällä add()-metodia?

question mark

Mikä on Queue Javassa?

Select the correct answer

question mark

Mikä rajapinta edustaa Queuea Java Collections Frameworkissa?

Select the correct answer

question mark

Mikä on offer()-metodin tarkoitus Queue-rajapinnassa?

Select the correct answer

question mark

Mitä poll()-metodi tekee Queue-rajapinnassa?

Select the correct answer

question mark

Mikä luokka Javan java.util.concurrent -paketissa edustaa rajoitettua estävää jonoa?

Select the correct answer

question mark

Mitä tapahtuu, jos yrität lisätä alkion täyteen jonoon käyttämällä add()-metodia?

Select the correct answer

Oliko kaikki selvää?

Miten voimme parantaa sitä?

Kiitos palautteestasi!

Osio 2. Luku 1
some-alt