1. Aloittaminen

Ensimmäinen ohjelma

Ohjelman koodi on tietokoneelle annettava tekstimuotoinen kuvaus ohjelman toiminnasta. Tietokone suorittaa ohjelman toteuttamalla koodissa olevat komennot.

Seuraavassa on ensimmäisen Java-ohjelmamme koodi:

import java.util.*;

public class EkaOhjelma {
    private static Scanner input = new Scanner(System.in);

    public static void main(String[] args) {
	System.out.println("Ohjelmointi alkaa...");
	System.out.print("Mikä on nimesi? ");
	String nimi = input.nextLine();
	System.out.println("Hei vain, " + nimi + "!");
    }
}

Ohjelman tarkoituksena on toimia seuraavasti:

  1. Ohjelma näyttää tekstin "Ohjelmointi alkaa..."
  2. Ohjelma näyttää tekstin "Mikä on nimesi?"
  3. Ohjelma kysyy käyttäjältä nimen.
  4. Ohjelma näyttää tekstin "Hei vain, X!", jossa X on käyttäjän nimi.

Tässä vaiheessa ei ole tärkeää ymmärtää kaikkea ohjelman koodissa, vaan siinä esiintyvät asiat tulevat tutuksi kurssin aikana.

Ohjelman suoritus

Kurssilla käytetään NetBeans-ohjelmointiympäristöä, jonka saat käynnistettyä tietojenkäsittelytieteen laitoksen Linux-ympäristössä valitsemalla ylävalikosta Applications kohta Programming ja edelleen kohta NetBeans IDE.

Valitse File -> New Project uuden ohjelman aloittamiseksi. Esiin tulee seuraava ikkuna, josta riittää painaa Next:

Kirjoita sitten kohtiin Project Name ja Create Main Class ohjelman nimi (tässä tapauksessa EkaOhjelma) ja paina Finish.

Nyt avautuu tekstieditori, johon voit kirjoittaa ohjelman koodin. Editorissa on valmiina ohjelman pohja, jonka voit korvata tämän sivun alussa olevalla koodilla. Ohjelman pitäisi näyttää nyt tältä:

Kun painat Shift + F6, ohjelman suoritus alkaa. Ohjelmaan liittyvät tekstit ilmestyvät ikkunan alalaitaan. Tänne voit myös kirjoittaa nimesi, jota ohjelma kysyy. Suorituksen pitäisi näyttää tältä:

NetBeans on monipuolinen ohjelmointiympäristö, mutta tällä hetkellä riittää tietää, kuinka ohjelmia luodaan ja suoritetaan.

Jos sait yllä olevan ohjelman toimimaan, ohjelmointiympäristösi on kunnossa ja voit jatkaa seuraavaan lukuun.

Aloittaminen

2. Tulostaminen

Ohjelman runko

Kurssin alkuvaiheessa ohjelmamme runko on aina seuraava:

import java.util.*;

public class OhjelmanNimi {
    private static Scanner input = new Scanner(System.in);

    public static void main(String[] args) {
	...
    }
}

Kolmen pisteen (...) kohdalle tulee ohjelman varsinainen sisältö, ja rungon alkuosa ja loppuosa toistuvat aina muuttumattomina. Niiden merkitykseen palataan myöhemmin.

Tulostaminen

Tulostaminen tarkoittaa, että ohjelma näyttää tekstiä ruudulla.

Javan tulostuskomennot ovat seuraavat.

Esimerkki

Tarkastellaan seuraavaa ohjelmaa:

System.out.println("Ensimmäinen rivi");
System.out.println("Toinen rivi");
System.out.println("Kolmas rivi");

Ohjelma tulostaa seuraavat kolme riviä:

Ensimmäinen rivi
Toinen rivi
Kolmas rivi

Kokeile, että saat ohjelman suoritettua NetBeansissa. Ohjelman nimeksi sopii vaikkapa Tulostaminen. Ohjelman ympärille tulee sivun yläosassa oleva runko, ja tämä käytäntö jatkuu tulevissa esimerkeissä.

Havaintoja

Ohjelmasta voidaan havaita seuraavat Java-kielen asiat:

Rivinvaihdot

Komento System.out.print ei lisää tekstin loppuun rivinvaihtoa. Tätä havainnollistaa seuraava ohjelma:

System.out.print("Nämä ");
System.out.print("sanat ");
System.out.print("tulevat ");
System.out.print("samalle ");
System.out.println("riville.");

Ohjelman tulostus on seuraava:

Nämä sanat tulevat samalle riville.

Tässä viimeinen komento on kuitenkin System.out.println, jotta viimeisen sanan jälkeen tulee rivinvaihto.

Erikoismerkinnät

Seuraavilla merkinnöillä on erikoismerkitys:

Seuraava ohjelma esittelee erikoismerkintöjä:

System.out.print("Ensimmäinen rivi\nToinen rivi\nKolmas rivi\n");
System.out.println("System.out.println(\"abc\");");

Ohjelman tulostus on seuraava:

Ensimmäinen rivi
Toinen rivi
Kolmas rivi
System.out.println("abc");

Luvut ja laskut

Tekstin sijasta voidaan tulostaa myös lukuja ja laskujen tuloksia:

System.out.println(12);
System.out.println(1 + 2 + 3 + 4 + 5);
System.out.println(12345 * 54321);

Ohjelman tulostus on seuraava:

12
15
670592745

Tekstiä ja lukuarvoja voi myös yhdistää +-merkillä:

System.out.println("Summa:" + (1 + 2 + 3 + 4 + 5));
System.out.println("Vuorokaudessa on " + (60 * 60 * 24) + " sekuntia.");

Ohjelman tulostus on seuraava:

Summa: 15
Vuorokaudessa on 86400 sekuntia.

Kommentti

Kommentti on koodissa oleva huomautus, joka ei vaikuta ohjelman toimintaan. Kommentin avulla koodin toimintaa voi selventää koodin lukijalle. Kuitenkin kannattaa pyrkiä siihen, että koodi on muutenkin niin selvää, että kommentteja ei juuri tarvitse.

Kommentin saa kirjoittamalla riville //, jolloin rivin loppuosasta tulee kommentti.

Kommentti voi näyttää seuraavalta:

// vuorokauden sekuntien määrä
System.out.println(60 * 60 * 24);

NetBeans-vinkki

Komentoa System.out.println tarvitsee hyvin usein. Voit kirjoittaa komennon nopeasti NetBeansissa kirjoittamalla sout ja painamalla Tab-näppäintä.

Muuttujat

3. Muuttujat

Muuttuja

Muuttuja on muistipaikka, jossa ohjelma voi säilyttää tarvitsemaansa tietoa.

Muuttujan nimi on tunnus, jolla siihen viitataan ohjelmassa. Muuttujan nimessä voi olla kirjaimia (az ja AZ) sekä numeroita (09), mutta nimi ei saa alkaa numerolla.

Muuttujan tyyppi tarkoittaa, millaista tietoa muuttujaan voi tallentaa. Javan tärkeimmät muuttujatyypit ovat seuraavat:

Muuttujan arvo tarkoittaa muuttujan sisältöä tietyllä ohjelman suorituksen hetkellä. Nimensä mukaisesti muuttujan arvo voi muuttua.

Esimerkki

Seuraavassa esimerkissä määritellään muuttujat nimi ja ika. Muuttujien arvoiksi laitetaan "Aapeli" ja 31, minkä jälkeen arvot tulostetaan.

String nimi = "Aapeli";
int ika = 31;
System.out.println(nimi + " on " + ika + " vuotta vanha.");

Ohjelman tulostus on seuraava:

Aapeli on 31 vuotta vanha.

Määrittely

Muuttuja täytyy aina määritellä, ennen kuin sitä voi alkaa käyttää. Määrittelyssä ilmoitetaan muuttujan tyyppi, nimi ja aloitusarvo. Määrittelyn kirjoitustapa on seuraava:

[tyyppi] [nimi] = [aloitusarvo];

Määrittelyn jälkeen muuttujaan voi viitata sille annetulla nimellä. Muuttujan nimi on ohjelmoijan päätettävissä, mutta nimi kannattaa valita kuvaavaksi, jotta siitä näkee muuttujan käyttötarkoituksen.

Muuttaminen

Muuttujan arvoa voi muuttaa seuraavasti:

[nimi] = [uusi arvo];

Muuttujan uuden arvon muodostuksessa voi käyttää sen vanhaa arvoa sekä muiden muuttujien arvoja.

Tarkastellaan seuraavaa ohjelmaa:

int a = 3;
int b = 1;
int c = 8;
a = 4;
b = b + 1;
c = c - 2;
b = 5;
b = a + b;
c = a * b;
a = 2 * b - 3;
System.out.println(a + " " + b + " " + c);

Ohjelman tulostus on seuraava:

15 9 36

Ohjelmassa tapahtuu seuraavaa:

koodiselityslopputulos
int a = 3;
int b = 1;
int c = 8;
muuttujien määrittely a = 3, b = 1, c = 8
a = 4; a saa arvon 4 a = 4, b = 1, c = 8
b = b + 1; b:n arvo kasvaa 1:llä a = 4, b = 2, c = 8
c = c - 2; c:n arvo vähenee 2:lla a = 4, b = 2, c = 6
b = 5; b saa arvon 5 a = 4, b = 5, c = 6
b = a + b; b saa arvokseen a:n ja b:n summan a = 4, b = 9, c = 6
c = a * b; c saa arvokseen a:n ja b:n tulon a = 4, b = 9, c = 36
a = 2 * b - 3; a saa arvokseen 2 * b - 3 a = 15, b = 9, c = 36

Äskeisen esimerkin ymmärtäminen on tärkeää. Älä mene eteenpäin, ennen kuin olet ymmärtänyt kokonaan, mitä ohjelmassa tapahtuu.

Lyhennysmerkintöjä

Tietyt muuttujien muutokset ovat hyvin tavallisia. Javassa ovat käytössä mm. seuraavat lyhennysmerkinnät:

koodilyhennys
a = a + 1a++
a = a - 1a--
a = a + ba += b
a = a - ba -= b

Seuraavat kaksi ohjelmaa toimivat samoin:

koodilyhennys
int a = 2;
a = a + 1;
System.out.println(a);
a = a + 3;
System.out.println(a);
int a = 2;
a++;
System.out.println(a);
a += 3;
System.out.println(a);

Arvo käyttäjältä

Tyypillinen tapa saada muuttujalle arvo on lukea se käyttäjältä. Seuraava komento lukee merkkijonon käyttäjältä:

String merkkijono = input.nextLine();

Kokonaislukujen ja desimaalilukujen lukeminen on hieman vaikeampaa, koska ne pitää muuttaa merkkijonosta lukuarvoiksi. Tämä onnistuu seuraavasti:

int kokonaisluku = Integer.parseInt(input.nextLine());
double desimaaliluku = Double.parseDouble(input.nextLine());

Seuraava ohjelma kysyy käyttäjän nimen ja iän. Sitten ohjelma tulostaa ne uudestaan.

System.out.print("Mikä on nimesi? ");
String nimi = input.nextLine();
System.out.print("Kuinka vanha olet? ");
int ika = Integer.parseInt(input.nextLine());
System.out.println("Nimesi on " + nimi + " ja olet " + ika + " vuotta vanha.");

Ohjelman tulostus voi olla seuraava:

Mikä on nimesi? Aapeli
Kuinka vanha olet? 31
Nimesi on Aapeli ja olet 31 vuotta vanha.

Tässä punaisella kirjoitettu teksti tarkoittaa ohjelman käyttäjän kirjoittamaa tekstiä. Tämä käytäntö jatkuu tulevissa esimerkeissä.

Esimerkki: Tarina

Seuraava ohjelma kysyy käyttäjän nimen ja tulostaa tarinan, jonka päähenkilönä käyttäjä on.

System.out.print("Anna nimesi: ");
String nimi = input.nextLine();
System.out.println();
System.out.println("Syrjäisessä laaksossa asui " + nimi + ",");
System.out.println("joka oli ammatiltaan lammaspaimen.");
System.out.println(nimi + " oli vasta herännyt,");
System.out.println("kun pihaan ratsasti tumma-asuinen ritari.");
System.out.println("Pian " + nimi + " saisi kuulla, että hänet oli");
System.out.println("valittu tärkeään tehtävään...");

Ohjelman tulostus voi olla seuraava:

Anna nimesi: Aapeli

Syrjäisessä laaksossa asui Aapeli,
joka oli ammatiltaan lammaspaimen.
Aapeli oli vasta herännyt,
kun pihaan ratsasti tumma-asuinen ritari.
Pian Aapeli saisi kuulla, että hänet oli
valittu tärkeään tehtävään...

Tai myös seuraava:

Anna nimesi: Maija

Syrjäisessä laaksossa asui Maija,
joka oli ammatiltaan lammaspaimen.
Maija oli vasta herännyt,
kun pihaan ratsasti tumma-asuinen ritari.
Pian Maija saisi kuulla, että hänet oli
valittu tärkeään tehtävään...

Huomaa komento System.out.println ilman tulostettavaa tekstiä: se saa aikaan tyhjän rivin.

Muuttujan tyypin valinta

Mistä tietää, mikä tyyppi on sopiva muuttujalle? Esimerkiksi luvun 12 voi tallentaa merkkijonona, kokonaislukuna ja desimaalilukuna:

String a = "12";
int b = 12;
double c = 12.0;

Muuttujan tyyppi kannattaa valita muuttujan käyttötarkoituksen mukaan. Jos muuttujalla on tarkoitus laskea, lukuarvotyypit ovat luonteva valinta. Jos taas muuttujaa käsitellään tekstin tavoin, sen kannattaa olla merkkijono.

Lukuarvot kannattaa yleensä tallentaa int-tyyppisinä. Vain jos lukuarvoissa tarvitaan desimaaliosaa, double-tyyppi on perusteltu.

Jakolasku

Yhteenlasku, vähennyslasku ja kertolasku toimivat Javassa luonnollisella tavalla, mutta jakolasku saattaa tuottaa yllätyksiä.

Jos jakolaskun molemmat luvut ovat kokonaislukuja, myös tulos on kokonaisluku, vaikka todellisuudessa jako ei menisi tasan. Jos taas ainakin toinen luvuista on desimaaliluku, tulos on desimaaliluku.

Seuraavan koodin toiminta voi yllättää:

int luku1 = 3;
int luku2 = 5;
double tulos = luku1 / luku2;
System.out.println(tulos);

Koodin tulostus on seuraava:

0.0

Vaikka muuttujan tulos tyyppi on double, tuloksen desimaaliosa on kadonnut.

Ratkaisu ongelmaan on muuttaa toinen jakolaskussa olevista luvuista desimaaliluvuksi. Tämän voi tehdä vaikkapa seuraavasti:

double tulos = (double)luku1 / luku2;

Nyt koodin tulostus on haluttu:

0.6

Javan nimeämiskäytäntö

Java-kielessä muuttujat nimetään tavallisesti niin, että muuttujan nimi alkaa pienellä, mutta jos nimessä on monta sanaa, kaikki seuraavat sanat alkavat suurella.

Tähän käytäntöön ei ole mitään syvällistä syytä, mutta se on järkevää omaksua, koska käytännöstä poikkeava koodi näyttää oudolta kokeneen Java-ohjelmoijan silmissä.

Seuraavat muuttujanimet vastaavat käytäntöä:

if-rakenne

4. if-rakenne

if-rakenne

if-rakenteen avulla ohjelman toiminnan saa riippumaan muuttujien arvoista.

Rakenteen tavallisimmat muodot ovat seuraavat:

Muoto 1:

if ([ehto]) {
    [koodi]
}

Tässä ohjelma suorittaa kohdassa [koodi] olevan koodin, jos [ehto] pitää paikkansa.

Muoto 2:

if ([ehto]) {
    [koodi1]
} else {
    [koodi2]
}

Tässä ohjelma suorittaa kohdassa [koodi1] olevan koodin, jos [ehto] pitää paikkansa, ja muussa tapauksessa kohdassa [koodi2] olevan koodin.

Esimerkki: Salasana

Seuraava ohjelma kysyy käyttäjältä salasanan. Sitten ohjelma kertoo, oliko salasana oikein. Tässä oikea salasana on "kissa".

System.out.print("Anna salasana: ");
String salasana = input.nextLine();
if (salasana.equals("kissa")) {
    System.out.println("Oikein meni!");
} else {
    System.out.println("Väärin meni!");
}

Esimerkkejä ohjelman suorituksesta:

Anna salasana: kissa
Oikein meni!
Anna salasana: koira
Väärin meni!

Esimerkki: Pituus

Seuraava ohjelma varmistaa, että muuttujalle pituus ei tule negatiivista arvoa. Jos pituus on alle 0, ohjelma muuttaa sen arvoksi 0.

System.out.print("Anna pituus: ");
int pituus = Integer.parseInt(input.nextLine());
if (pituus < 0) {
    pituus = 0;
}
System.out.println("Pituus: " + pituus);

Esimerkkejä ohjelman suorituksesta:

Anna pituus: 5
Pituus: 5
Anna pituus: -2
Pituus: 0

Ehdot

if-rakenteessa oleva ehto liittyy yleensä muuttujien arvoon. Äskeisissä esimerkeissä ehdot olivat "muuttujan salasana arvo on kissa" ja "muuttujan pituus arvo on alle 0".

Merkkijonoista halutaan yleensä tarkistaa, ovatko ne samat. Tämä onnistuu equals-komennolla esimerkin mukaisesti.

Lukuarvoista halutaan yleensä tarkistaa niiden suuruusjärjestys. Käytössä ovat merkinnät == (luvut ovat samat), != (luvut eivät ole samat), < (vasen luku on pienempi), > (vasen luku on suurempi) <= (vasen luku on sama tai pienempi) ja >= (vasen luku on sama tai suurempi).

Monta ehtoa

Ehtoja voidaan yhdistää seuraavilla merkinnöillä:

Lisäksi ehdon voi muuttaa käänteiseksi seuraavasti:

Esimerkki: Tunnus ja salasana

Seuraava ohjelma vaatii, että käyttäjä antaa oikean tunnuksen (aapeli) ja oikean salasanan (kissa).

System.out.print("Anna tunnus: ");
String tunnus = input.nextLine();

System.out.print("Anna salasana: ");
String salasana = input.nextLine();

if (tunnus.equals("aapeli") && salasana.equals("kissa")) {
    System.out.println("Oikein meni!");
    System.out.println("Tervetuloa järjestelmään...");
} else {
    System.out.println("Väärin meni!");
    System.out.println("Yritä vielä uudestaan...");
}

Esimerkkejä ohjelman suorituksesta:

Anna tunnus: aapeli
Anna salasana: kissa
Oikein meni!
Tervetuloa järjestelmään...
Anna tunnus: aapeli
Anna salasana: koira
Väärin meni!
Yritä vielä uudestaan...
Anna tunnus: maija
Anna salasana: koira
Väärin meni!
Yritä vielä uudestaan...

Pitkä if-rakenne

if-rakenteesta on myös olemassa pitkä muoto, jossa voi olla monia ehtoja.

Muoto 3:

if ([ehto1]) {
    [koodi1]
} else if ([ehto2]) {
    [koodi2]
} else if ([ehto3]) {
    [koodi3]
...
} else if ([ehton]) {
    [koodin]
}

Tässä ohjelma valitsee ensimmäisen ehdon, joka pitää paikkansa, ja suorittaa sitä vastaavan koodin. Lopussa voi olla vielä else-osa, jonne mennään, jos mikään ehto ei pidä paikkaansa.

Esimerkki: Iän tarkistaminen

Seuraava ohjelma kysyy käyttäjän iän ja tulostaa siitä kommentin alla olevan taulukon mukaisesti.

ikäkommentti
alle 0Ikä ei ole mahdollinen!
0...30Olet vielä nuori!
31...70Olet keski-ikäinen!
71...120Olet jo vanha!
yli 120Ikä ei ole mahdollinen!
System.out.print("Kuinka vanha olet? ");
int ika = Integer.parseInt(input.nextLine());

if (ika < 0 || ika > 120) {
    System.out.println("Ikä ei ole mahdollinen!");
} else if (ika <= 30) {
    System.out.println("Olet vielä nuori!");
} else if (ika <= 70) {
    System.out.println("Olet keski-ikäinen!");
} else {
    System.out.println("Olet jo vanha!");
}

Esimerkkejä ohjelman suorituksesta:

Kuinka vanha olet? 15
Olet vielä nuori!
Kuinka vanha olet? 47
Olet keski-ikäinen!
Kuinka vanha olet? -2
Ikä ei ole mahdollinen!

Varmista, että ymmärrät kokonaan yllä olevan koodin toiminnan. Ohjelma valitsee ensimmäisen paikkansa pitävän ehdon ja suorittaa sitä vastaavan koodin. Myöhempien ehtojen koodeja ei suoriteta, vaikka ehdot pitäisivät paikkansa.

Sisentäminen

Sisentäminen tarkoittaa, että koodirivien alkuun laitetaan välilyöntejä koodin rakenteen mukaisesti. Esimerkiksi if-rakenteen sisällä oleva koodi on tapana sisentää, jolloin koodista näkee helposti, miten if-rakenne on muodostunut.

Sisentäminen saattaa tuntua aluksi turhalta, mutta sitä oppii kyllä arvostamaan myöhemmin. NetBeansin avulla sisentämisen opetteleminen on helppoa, koska voit painaa Shift + Alt + F, jolloin koodi sisentyy automaattisesti.

Merkkijonojen vertailu

Seuraava koodi vaikuttaa luontevalta, mutta se ei toimi!

if (salasana == "kissa") {
    System.out.println("Oikein meni!");
}

Vaikka Java hyväksyy koodin, if-rakenne ei tunnista tilannetta, jossa muuttujassa salasana on merkkijono "kissa".

Ilmiön syy selviää myöhemmin kurssilla, mutta tällä hetkellä riittää tietää, että seuraava koodi toimii:

if (salasana.equals("kissa")) {
    System.out.println("Oikein meni!");
}
for-silmukka

5. for-silmukka

for-silmukka

for-silmukka käy läpi tietyllä välillä olevat luvut ja suorittaa jokaisen luvun kohdalla samanlaisen koodin.

Esimerkki

Tavallisin for-silmukan muoto on seuraava:

System.out.print("Anna yläraja: ");
int ylaraja = Integer.parseInt(input.nextLine());

for (int i = 0; i < ylaraja; i++) {
    System.out.println(i);
}

Esimerkkejä ohjelman tulostuksesta:

Anna yläraja: 5
0
1
2
3
4
Anna yläraja: 8
0
1
2
3
4
5
6
7

Tässä for-silmukka käy läpi kokonaislukuja kasvavassa järjestyksessä. Ensimmäinen luku on 0, ja silmukka jatkuu ylärajaan asti. Muuttuja i saa arvokseen yksi kerrallaan kunkin luvuista.

Yleinen muoto

Yleinen for-silmukan muoto on seuraava:

for ([alkuarvo]; [jatkamisehto]; [muutos]) {
    [koodi]
}

Kohdassa [alkuarvo] määritellään muuttuja, jolle annetaan alkuarvoksi ensimmäinen läpikäytävä luku. Yllä olevassa esimerkissä määriteltiin muuttuja i, jolle annettiin alkuarvoksi 0.

Kohdassa [jatkamisehto] kerrotaan, miten kauan for-silmukka jatkuu. Yllä olevassa esimerkissä ehtona oli, että muuttujan arvo on ylärajaa pienempi.

Kohdassa [muutos] muutetaan muuttujaa halutulla tavalla. Yllä olevassa esimerkissä muuttujan arvoa kasvatettiin aina yhdellä.

Seuraavassa on esimerkkejä erilaisista for-silmukoista:

silmukkatulostus
for (int i = 2; i < 7; i++) {
    System.out.println(i);
}
2
3
4
5
6
for (int i = 2; i <= 7; i++) {
    System.out.println(i);
}
2
3
4
5
6
7
for (int i = 2; i < 9; i += 2) {
    System.out.println(i);
}
2
4
6
8
for (int i = 7; i > 2; i--) {
    System.out.println(i);
}
7
6
5
4
3
for (int i = 7; i >= 2; i--) {
    System.out.println(i);
}
7
6
5
4
3
2

Mieti jokaisesta yllä olevasta silmukasta, miksi se tulostaa annetut luvut. Tämän jälkeen voit siirtyä eteenpäin.

Esimerkki: Viestin toisto

Seuraava ohjelma toistaa käyttäjän antaman viestin halutun määrän kertoja:

System.out.print("Anna viesti: ");
String viesti = input.nextLine();
System.out.print("Anna toistokerrat: ");
int kerrat = Integer.parseInt(input.nextLine());

for (int i = 0; i < kerrat; i++) {
    System.out.println(viesti);
}

Ohjelman tulostus voi olla seuraava:

Anna viesti: Kappas kippis!
Anna toistokerrat: 5
Kappas kippis!
Kappas kippis!
Kappas kippis!
Kappas kippis!
Kappas kippis!

Tässä tapauksessa for-silmukassa olevaa muuttujaa i ei käytetty mitenkään silmukan sisällä olevassa koodissa. Silmukan ainoa tarkoitus oli suorittaa sama koodi halutun määrän kertoja.

Esimerkki: Kolmen luvun summa

Silmukan sisään voi kirjoittaa mitä tahansa koodia. Seuraava ohjelma kysyy käyttäjältä kolme lukua ja ilmoittaa lopuksi niiden summan.

System.out.println("Ohjelma kysyy sinulta kolme lukua...");
int summa = 0;
for (int i = 1; i <= 3; i++) {
    System.out.print("Anna luku " + i + ": ");
    int luku = Integer.parseInt(input.nextLine());
    summa = summa + luku;
}
System.out.println("Lukujen summa: " + summa);
Ohjelman suoritus voi olla seuraava:
Ohjelma kysyy sinulta kolme lukua...
Anna luku 1: 5
Anna luku 2: 2
Anna luku 3: 8
Lukujen summa: 15

Huomaa muuttujan summa käyttötapa: muuttujan arvo on aluksi 0, ja sitten siihen lisätään yksi kerrallaan käyttäjän antamia lukuja. Yllä olevassa tilanteessa muuttujan arvo muuttuu seuraavasti:

Ymmärräthän varmasti, mihin koodin toiminta perustuu?

Muuttujan nimi

Tähän mennessä kaikissa esimerkeissä for-silmukan muuttujan nimi on ollut i. Näin ei ole kuitenkaan pakko olla, vaan nimi voi olla mikä tahansa kelvollinen muuttujan nimi. Kuitenkin yleiseksi tavaksi ohjelmoinnissa on tullut, että for-silmukan muuttujan nimeksi laitetaan i.

Esimerkki: Kertotaulu

Joskus for-silmukkoja on useampia sisäkkäin. Näin on seuraavassa esimerkissä, joka tulostaa kertotaulun. Tässä ulommassa silmukassa muuttujana on i ja sisemmässä silmukassa muuttujana on j.

for (int i = 1; i <= 10; i++) {
    for (int j = 1; j <= 10; j++) {
        System.out.print((i * j) + " ");
    }
    System.out.println();
}

Ohjelman tulostus on seuraava:

1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100

Ohjelman tulostus ei ole tällaisenaan kovin kaunis, koska luvut ovat eri riveillä eri kohdissa. Asian voi korjata komennolla System.out.format, jolla voi tulostaa luvun annetun levyiseen kenttään. Seuraava koodi esittelee komentoa:

for (int i = 1; i <= 10; i++) {
    for (int j = 1; j <= 10; j++) {
        System.out.format("%4d", (i * j));
    }
    System.out.println();
}

Nyt ohjelman tulostus on seuraava:

   1   2   3   4   5   6   7   8   9  10
   2   4   6   8  10  12  14  16  18  20
   3   6   9  12  15  18  21  24  27  30
   4   8  12  16  20  24  28  32  36  40
   5  10  15  20  25  30  35  40  45  50
   6  12  18  24  30  36  42  48  54  60
   7  14  21  28  35  42  49  56  63  70
   8  16  24  32  40  48  56  64  72  80
   9  18  27  36  45  54  63  72  81  90
  10  20  30  40  50  60  70  80  90 100
while-silmukka

6. while-silmukka

while-silmukka

while-silmukka toistaa tiettyä koodia niin kauan, kuin haluttu ehto pitää paikkansa.

Silmukan rakenne on seuraava:

while ([ehto]) {
    [koodi]
}

Esimerkki

Seuraava ohjelma tulostaa luvut väliltä 1–10 while-silmukan avulla:

int luku = 1;
while (luku <= 10) {
    System.out.println(luku);
    luku = luku + 1;
}

Ohjelman tulostus on seuraava:

1
2
3
4
5
6
7
8
9
10

Tässä muuttuja luku on aluksi 1. Silmukan jokaisella kierroksella ohjelma tulostaa muuttujan luku ja kasvattaa sen arvoa yhdellä. Silmukka jatkuu niin kauan, kuin muuttujan luku arvo on korkeintaan 10.

Totuusarvot

Nyt on tullut aika esitellä uusi Javan tietotyyppi. Totuusarvo on tyyppi, jolla on vain kaksi mahdollista arvoa: true (tosi) ja false (epätosi).

Totuusarvoja on jo käytetty paljon, vaikka niitä ei ole mainittu nimeltä. Kaikki ehdot if-rakenteessa ja silmukoissa ovat nimittäin totuusarvoja.

Totuusarvotyypin tunnus on boolean. Totuusarvoja voi käsitellä samaan tapaan kuin merkkijonoja ja lukuja, kuten seuraava ohjelma havainnollistaa:

boolean salasanaOikein = salasana.equals("kissa");
if (salasanaOikein) {
    System.out.println("Salasana on oikein!");
}

Tässä muuttuja salasanaOikein saa arvon true, jos salasana on kissa, ja muuten arvon false. Tämän jälkeen if-rakenteen sisällä oleva koodi suoritetaan, jos ehdon totuusarvo on true eli muuttujan arvo on true.

Tällä hetkellä saattaa tuntua vaikealta keksiä käyttöä totuusarvomuuttujalle, koska esimerkiksi yllä olevan koodin voisi kirjoittaa lyhyemmin ilman muuttujaa. Myöhemmin kuitenkin huomaamme, että totuusarvomuuttuja voi olla varsin hyödyllinen.

Ikuinen silmukka

Ikuinen silmukka on silmukka, jonka toistamista ei ole rajoitettu. Javassa ikuinen silmukka voidaan luoda seuraavasti:

while (true) {
    [koodi]
}

Tämä silmukka jatkuu niin kauan, kuin ehto true on tosi – mutta tämä ehto on aina tosi. Ongelmaksi näyttää siis tulevan, että silmukka ei pääty milloinkaan.

Silmukan lopettamiseen on kuitenkin myös toinen tapa: komento break. Tämä komento silmukan sisällä lopettaa silmukan välittömästi riippumatta silmukan ehdosta.

Tyypillinen ikuinen silmukka näyttää seuraavalta:

while (true) {
    ...
    if ([ehto]) {
        break;
    }
    ...
}

Seuraavat esimerkit näyttävät, mitä hyötyä ikuisesta silmukasta voi olla.

Esimerkki: Salasana

Seuraava ohjelma kysyy käyttäjältä salasanaa, kunnes käyttäjä antaa oikean salasanan.

while (true) {
    System.out.print("Anna salasana: ");
    String salasana = input.nextLine();
    if (salasana.equals("kissa")) {
        break;
    }
    System.out.println("Väärin meni!");
}
System.out.println("Tervetuloa!");

Ohjelman suoritus voi olla seuraava:

Anna salasana: koira
Väärin meni!
Anna salasana: lehmä
Väärin meni!
Anna salasana: kissa
Tervetuloa!

Esimerkki: Iän kysyminen

Seuraava ohjelma kysyy käyttäjältä ikää, kunnes käyttäjä antaa kelvollisen iän:

while (true) {
    System.out.print("Kuinka vanha olet? ");
    int ika = Integer.parseInt(input.nextLine());
    if (ika >= 0 && ika <= 120) {
        break;
    }
    System.out.println("Ikä ei kelpaa!");
}
System.out.println("Kiitos!");

Ohjelman suoritus voi olla seuraava:

Kuinka vanha olet? -5
Ikä ei kelpaa!
Kuinka vanha olet? 139
Ikä ei kelpaa!
Kuinka vanha olet? 56
Kiitos!

Tässä silmukan lopettamisen ehtona on, että ikä on välillä 0–120.

Silmukan muodostaminen

Silmukan muodostamiseen on yleensäkin kaksi eri tapaa:

Seuraavat koodit havainnollistavat asiaa:

ehto rungossakäytössä break
String salasana = "";
while (!salasana.equals("kissa")) {
    System.out.print("Anna salasana: ");
    salasana = input.nextLine();
}
while (true) {
    System.out.print("Anna salasana: ");
    String salasana = input.nextLine();
    if (salasana.equals("kissa")) {
        break;
    }
}

Molemmat koodit toimivat, ja on makuasia, kumpaa haluaa käyttää. Koodien ajattelutapa on kuitenkin erilainen: vasemmassa koodissa ajatellaan "silmukka jatkuu niin kauan, kuin salasana ei ole kissa" kun taas oikeassa koodissa ajatellaan "silmukka jatkuu, kunnes salasana on kissa".

Muuttujien näkyvyys

Seuraava asia on hyvä tiedostaa: Jos muuttujan määrittelee silmukan sisällä, sen alkuarvo palautetaan silmukan jokaisella kierroksella eikä muuttujaa voi käyttää muualla kuin silmukan sisällä.

Esimerkiksi seuraava koodi ei toimi:

while (summa < 100) {
    int summa = 0;    
    summa = summa + 1;
}

Nyt muuttuja summa nollautuu silmukan joka kierroksella eikä siihen voi edes viitata silmukan ehdossa.

for vai while?

Mistä tietää, kannattaako toistaminen tehdä for-silmukan vai while-silmukan avulla?

Perussääntö on, että jos toistokertojen määrä on tiedossa ennen silmukan aloittamista (esim. koodi toistetaan 5 kertaa), for-silmukka on luonteva valinta, ja muussa tapauksessa while-silmukka sopii ehkä paremmin.

Kuitenkin kummalla tahansa silmukalla voi toteuttaa minkä tahansa toistorakenteen. Niinpä toinen silmukka on tavallaan "turha". Molemmat silmukat ovat Javassa, koska molemmille on luontevia käyttötilanteita.

Hauska lisätehtävä: Mieti, miten voit korvata for-silmukan while-silmukalla ja päinvastoin.

ArrayList

7. ArrayList

Tavallisten muuttujien rajoituksena on, että jokaisessa on vain yksi tieto. Jos ohjelman pitää muistaa kolme lukua, tarvitaan kolme muuttujaa. Entä jos ohjelman pitäisi muistaa tuhat lukua tai miljoona lukua?

ArrayList

ArrayList on listarakenne, johon voidaan tallentaa vaihteleva määrä arvoja. Etuna erillisiin muuttujiin verrattuna on, että listaa voidaan käsitellä samanlaisella koodilla riippumatta sen arvojen määrästä.

Listan määrittely

Uusi lista määritellään seuraavalla komennolla:

ArrayList<[tyyppi]> [nimi] = new ArrayList<[tyyppi]>();

Tässä [tyyppi] tarkoittaa, millaisia arvoja listalle voi tallentaa, ja [nimi] on tunnus, jolla listaan viitataan koodissa.

Listan määrittelyssä tyypit eroavat hieman muuttujien tyypistä:

muuttujan määrittelyssälistan määrittelyssä
StringString
intInteger
doubleDouble

Siis String määritellään molemmissa tapauksissa samoin, mutta lukutyyppien määrittelyssä on eroja. Tämä ilmiö saa selityksen myöhemmin, mutta nyt riittää vain tietää asia.

Lisääminen ja hakeminen

Seuraava ohjelma lisää listalle kolme nimeä (Aapeli, Maija ja Väinö). Sitten ohjelma tulostaa nimien määrän ja nimet yksi kerrallaan.

ArrayList<String> nimet = new ArrayList<String>();

nimet.add("Aapeli");
nimet.add("Maija");
nimet.add("Väinö");

System.out.println("Nimien määrä: " + nimet.size());

System.out.println("Eka: " + nimet.get(0));
System.out.println("Toka: " + nimet.get(1));
System.out.println("Kolmas: " + nimet.get(2));

Ohjelman tulostus on seuraava:

Nimien määrä: 3
Eka: Aapeli
Toka: Maija
Kolmas: Väinö

Lista on tallennettu seuraavasti tietokoneen muistiin:

kohta012
sisältö"Aapeli""Maija""Väinö"

Tässä tuli esille kolme listaan liittyvää komentoa:

Huomaa, että listan kohtien numerointi alkaa nollasta. Ensimmäinen arvo on siis kohdassa 0, toinen kohdassa 1 jne.

Onko arvo listalla?

Komennolla contains voi tarkistaa, onko tietty arvo listalla. Seuraavassa esimerkissä listalle laitetaan viikonpäivien nimet suomeksi, ja ohjelma tarkistaa, antaako käyttäjä viikonpäivän nimen.

ArrayList<String> paivat = new ArrayList<String>();

paivat.add("maanantai");
paivat.add("tiistai");
paivat.add("keskiviikko");
paivat.add("torstai");
paivat.add("perjantai");
paivat.add("lauantai");
paivat.add("sunnuntai");

System.out.print("Anna viikonpäivä: ");
String paiva = input.nextLine();

if (paivat.contains(paiva)) {
    System.out.println("Kiitos!");
} else {
    System.out.println("Ei kelpaa!");
}

Esimerkkejä ohjelman suorituksesta:

Anna viikonpäivä: tiistai
Kiitos!
Anna viikonpäivä: selleri
Ei kelpaa!

Esimerkki: Toistuva luku

Seuraava ohjelma kysyy käyttäjältä lukuja, kunnes käyttäjä antaa saman luvun uudestaan. Lopuksi ohjelma tulostaa annettujen lukujen määrän. Ideana on tallentaa kaikki luvut listaan, jotta ohjelma pystyy tarkistamaan, onko käyttäjä antanut saman luvun jo aiemmin.

ArrayList<Integer> lista = new ArrayList<Integer>();

while (true) {
    System.out.print("Anna luku: ");
    int luku = Integer.parseInt(input.nextLine());
    if (lista.contains(luku)) {
        break;
    }
    lista.add(luku);
}
System.out.println("Annoit yhteensä " + lista.size() + " eri lukua.");

Ohjelman suoritus voi olla seuraava:

Anna luku: 3
Anna luku: 5
Anna luku: 2
Anna luku: 9
Anna luku: 5
Annoit yhteensä 4 eri lukua.

Listan läpikäynti

Listan läpikäyntiin on olemassa erityinen for-silmukan muoto, jonka merkintätapa on seuraava:

for ([tyyppi] [muuttuja] : [lista]) {
    [koodi]
}

Tässä [muuttuja] saa arvokseen yksi kerrallaan kunkin listalla olevan arvon. Muuttujan tyypin täytyy vastata listan arvojen tyyppiä.

Seuraava ohjelma tulostaa listan sisällön:

ArrayList<String> nimet = new ArrayList<String>();

nimet.add("Aapeli");
nimet.add("Maija");
nimet.add("Väinö");

for (String nimi : nimet) {
    System.out.println(nimi);
}

Ohjelman tulostus on seuraava:

Aapeli
Maija
Väinö

Listan tulostaminen

Listan sisällön voi myös tulostaa suoraan komennolla System.out.println. Tällöin listan sisältö tulostetaan hakasulkujen sisällä pilkkujen erottamana.

Seuraava ohjelma havainnollistaa asiaa:

ArrayList<String> nimet = new ArrayList<String>();

nimet.add("Aapeli");
nimet.add("Maija");
nimet.add("Väinö");

System.out.println(nimet);

Ohjelman tulostus on seuraava:

[Aapeli, Maija, Väinö]

Muita komentoja

Listan voi järjestää seuraavalla komennolla:

Collections.sort(lista);

Jos listalla on lukuja, ne järjestetään suuruusjärjestykseen. Jos taas listalla on merkkijonoja, ne järjestetään aakkosjärjestykseen.

Listan voi kääntää ympäri seuraavalla komennolla:

Collections.reverse(lista);

Listan järjestyksen voi sekoittaa seuraavalla komennolla:

Collections.shuffle(lista);

Esimerkki: Lottoarvonta

Seuraava ohjelma arpoo viikon lottonumerot eli 7 eri numeroa väliltä 1–39.

ArrayList<Integer> kaikki = new ArrayList<Integer>();

for (int i = 1; i <= 39; i++) {
    kaikki.add(i);
}

Collections.shuffle(kaikki);

ArrayList<Integer> oikeat = new ArrayList<Integer>();

for (int i = 0; i < 7; i++) {
    oikeat.add(kaikki.get(i));
}

Collections.sort(oikeat);

System.out.println("Lottonumerot:");
System.out.println(oikeat);

Ohjelman tulostus voi olla seuraava:

Lottonumerot:
[5, 7, 9, 14, 22, 26, 32]

Ohjelman toiminta on seuraava:

  1. Ohjelma lisää listalle kaikki mahdolliset lottonumerot väliltä 1–39.
  2. Ohjelma sekoittaa listan kaikki.
  3. Ohjelma lisää listan kaikki 7 ensimmäistä lottonumeroa listalle oikeat.
  4. Ohjelma järjestää listan oikeat.
  5. Ohjelma tulostaa listan oikeat.
Merkkijonot

8. Merkkijonot

Merkkijono ja merkki

Merkkijonon tietotyyppi String on tullut tutuksi jo aiemmissa luvuissa. Tämän lisäksi Javassa on tietotyyppi char, joka vastaa yhtä merkkiä. Seuraava koodi määrittelee ja tulostaa char-muuttujan:

char merkki = 'A';
System.out.println(merkki);

Ohjelman tulostus on seuraava:

A

Erona String-muuttujaan verrattuna char-muuttujassa on aina tasan yksi merkki, joka kirjoitetaan heittomerkkien (') sisään.

Merkkijonon koostumus

Merkkijonoon liittyvät seuraavat tärkeät komennot:

Esimerkiksi merkkijono "testi" on muistissa seuraavasti:

kohta01234
merkkitesti

Seuraava ohjelma esittelee komentojen käyttöä:

System.out.print("Anna merkkijono: ");
String merkkijono = input.nextLine();

int pituus = merkkijono.length();
System.out.println("Pituus: " + pituus);

char eka = merkkijono.charAt(0);
System.out.println("1. merkki: " + eka);
char kolmas = merkkijono.charAt(2);
System.out.println("3. merkki: " + kolmas);

System.out.println("Kaikki merkit:");
for (int i = 0; i < merkkijono.length(); i++) {
    char merkki = merkkijono.charAt(i);
    System.out.println("Kohdassa " + i + " on merkki " + merkki);
}

Ohjelman tulostus voi olla seuraava:

Anna merkkijono: testi
Pituus: 5
1. merkki: t
3. merkki: s
Kaikki merkit:
Kohdassa 0 on merkki t
Kohdassa 1 on merkki e
Kohdassa 2 on merkki s
Kohdassa 3 on merkki t
Kohdassa 4 on merkki i

Osa merkkijonosta

Komennolla substring pystyy erottamaan osan merkkijonosta. Komentoa voi käyttää kahdella tavalla:

Seuraavassa esimerkissä merkkijono on muistissa näin:

kohta012345 678
merkkiesimer kki

Erotetaan merkkijonosta kaksi osaa:

String merkkijono = "esimerkki";
String osa1 = merkkijono.substring(3);
System.out.println(osa1);
String osa2 = merkkijono.substring(2, 7);
System.out.println(osa2);

Ohjelman tulostus on seuraava:

merkki
imerk

Huomaa komennon erikoinen toiminta, kun lopetuskohta annetaan: viimeinen mukaan tuleva merkki on yksi merkki ennen lopetuskohtaa!

Haku merkkijonosta

Komento indexOf etsii kohdan, jossa merkkijonon osana on tietty merkki tai merkkijono. Jos kohtia on useita, komento kertoo ensimmäisen kohdan. Jos yhtään kohtaa ei ole, komento tuottaa arvon -1.

Seuraava ohjelma hakee merkkijonosta "esimerkki" käyttäjän antamaa merkkijonoa.

String merkkijono = "esimerkki";
System.out.print("Anna haettava merkkijono: ");
String haettava = input.nextLine();
int kohta = merkkijono.indexOf(haettava);
if (kohta == -1) {
    System.out.println("Haettavaa merkkijonoa ei ole");
} else {
    System.out.println("Haettava merkkijono alkaa kohdassa " + kohta);
}

Esimerkkitulostuksia:

Anna haettava merkkijono: merkki
Haettava merkkijono alkaa kohdassa 3
Anna haettava merkkijono: testi
Haettavaa merkkijonoa ei ole

Merkkikoodit

Javassa jokaista merkkiä vastaa merkkikoodi, joka on kokonaisluku. Esimerkiksi merkkiä 'A' vastaa merkkikoodi 65. Niinpä char-arvolla on kaksi vaihtoehtoista merkintätapaa: merkkiesitys ja koodiesitys.

Seuraavassa taulukossa on osa Javan merkistöstä merkkikoodeineen:

 33  !    34  "    35  #    36  $    37  %    38  &    39  '    40  (    41  )
 42  *    43  +    44  ,    45  -    46  .    47  /    48  0    49  1    50  2
 51  3    52  4    53  5    54  6    55  7    56  8    57  9    58  :    59  ;
 60  <    61  =    62  >    63  ?    64  @    65  A    66  B    67  C    68  D
 69  E    70  F    71  G    72  H    73  I    74  J    75  K    76  L    77  M
 78  N    79  O    80  P    81  Q    82  R    83  S    84  T    85  U    86  V
 87  W    88  X    89  Y    90  Z    91  [    92  \    93  ]    94  ^    95  _
 96  `    97  a    98  b    99  c   100  d   101  e   102  f   103  g   104  h
105  i   106  j   107  k   108  l   109  m   110  n   111  o   112  p   113  q
114  r   115  s   116  t   117  u   118  v   119  w   120  x   121  y   122  z

Merkin merkkikoodin saa selville näin:

char merkki = 'A';
System.out.println("Merkkikoodi: " + (int)merkki);

Vastaavasti merkkikoodin merkin saa selville näin:

int koodi = 65;
System.out.println("Merkki: " + (char)merkki);

Seuraava koodi tulostaa kirjaimet väliltä A–Z:

for (char i = 'A'; i <= 'Z'; i++) {
    System.out.print(i);
}
System.out.println();

Ohjelman tulostus on seuraava:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

Kuten tästä esimerkistä havaitaan, char-arvoja voi käsitellä hyvin samalla tavalla kuin lukuarvoja.

Matematiikka

9. Matematiikka

Jakojäännös

Jakojäännös tarkoittaa jakolaskussa yli jäävää kokonaislukua. Esimerkiksi jos luku 17 jaetaan luvulla 5, jakojäännös on 2, koska 3 · 5 = 15, mutta 2 jää yli.

Javassa jakojäännös lasketaan %-merkillä. Esimerkiksi seuraava ohjelma tulostaa luvun 2:

System.out.println(17 % 5);

Jakojäännöksellä on paljon sovelluksia ohjelmoinnissa. Ensinnäkin jakojäännöksen avulla voi tarkistaa luvun jaollisuuden jollain luvulla. Esimerkiksi jos täytyy selvittää, onko luku parillinen, riittää tarkistaa, onko luvun jakojäännös 2:lla 0:

System.out.print("Anna luku: ");
int luku = Integer.parseInt(input.nextLine());

if (luku % 2 == 0) {
    System.out.println("Luku on parillinen.");
} else {
    System.out.println("Luku on pariton.");
}

Myöhemmin kurssilla tulee vastaan muita jakojäännöksen sovelluksia.

Math-kirjasto

Javan osana on kirjasto Math, jossa on matematiikkaan liittyviä funktioita. Kirjastoon kuuluvat mm. seuraavat funktiot:

funktioselitys
Math.abs(x)itseisarvo
Math.min(x, y)pienempi luvuista x ja y
Math.max(x, y)suurempi luvuista x ja y
Math.pow(x, y)potenssilasku: xy
Math.sqrt(x)neliöjuuri

Seuraava ohjelma laskee luvun neliöjuuren:

System.out.print("Anna luku: ");
int luku = Integer.parseInt(input.nextLine());

System.out.println("Neliöjuuri: " + Math.sqrt(luku));

Satunnaisluvut

Satunnaislukugeneraattori tuottaa satunnaisia lukuja. Seuraava komento luo satunnaislukugeneraattorin:

Random arpoja = new Random();

Tämän jälkeen generaattorilta voi pyytää satunnaisia kokonaislukuja komennolla nextInt. Komennolle annetaan yläraja, ja sen tuottamat luvut ovat väliltä 0...yläraja-1.

Seuraava ohjelma arpoo satunnaisen luvun väliltä 0–9:

Random arpoja = new Random();
int luku = arpoja.nextInt(10);
System.out.println("Satunnainen luku: " + luku);

Ohjelman tulostuksia ovat esimerkiksi seuraavat:

Satunnainen luku: 3
Satunnainen luku: 7

Javan satunnaislukugeneraattorista puuttuu komento, jolla voisi hakea satunnaisen luvun kahden kokonaisluvun väliltä, koska alaraja 0 on kiinteä. Tämä ei ole kuitenkaan suuri ongelma, koska jos haluamme luvun väliltä a...b, voimme myös hakea luvun väliltä 0...(b - a) ja lisätä tulokseen a.

Seuraava esimerkki toteuttaa yllä olevan idean:

System.out.print("Anna alaraja: ");
int alaraja = Integer.parseInt(input.nextLine());
System.out.print("Anna yläraja: ");
int ylaraja = Integer.parseInt(input.nextLine());

Random arpoja = new Random();
int luku = arpoja.nextInt(ylaraja - alaraja + 1) + alaraja;
System.out.println("Satunnainen luku: " + luku);

Ohjelman suoritus voi olla seuraava:

Anna alaraja: 57
Anna yläraja: 65
Satunnainen luku: 63

Lukuarvot

Javan tyypit int ja double tuntuvat päältä päin melko samanlaisilta, mutta niiden käytössä on silti tärkeitä eroja.

Tyyppi int tallentaa kokonaisluvun tarkasti, mutta sen lukualue on melko rajattu: pienin mahdollinen int-luku on -2147483648 ja suurin mahdollinen int-luku on 2147483647.

Seuraavan ohjelman toiminta on yllättävä:

int luku = 2147483647;
luku = luku + 1;
System.out.println(luku);

Ohjelma tulostaa luvun -2147483648. Tässä int-muuttujaan yritettiin laittaa liian suuri luku, jolloin luvun arvo pyörähti ympäri negatiiviselle puolelle pienimpään mahdolliseen lukuun.

Suurempia kokonaislukuja varten Javassa on tyypit long ja BigInteger, joita ei kuitenkaan käsitellä tällä kurssilla.

Tyyppi double voi sisältää desimaaliluvun ja sen lukualue on suuri, mutta tyypin rajoituksena on, että monen luvun arvoa ei voida tallentaa tarkasti vaan arvo joudutaan pyöristämään. Niinpä double-tyyppiä käyttäessä harmina ovat mahdolliset pyöristysvirheet.

Seuraava ohjelma saa aikaan pyöristysvirheen:

double luku = 0.2;
luku = luku + 0.1;
System.out.println(luku);

Ohjelman tulostus on seuraava:

0.30000000000000004

Pyöristysvirheen vuoksi luku on 0.30000000000000004 eikä 0.3.

Metodit

10. Metodit

Metodi

Metodi on tietyn asian tekevä koodinpätkä. Olemme jo käyttäneet monia metodeita, vaikka niitä ei ole kutsuttu sillä nimellä. Esimerkiksi ArrayListin add on metodi, jolla saa lisättyä arvon listalle. Samoin merkkijonon length on metodi, jolla saa selville merkkijonon pituuden.

Tähän asti kaikki ohjelmamme on tehty seuraavaan runkoon:

import java.util.*;

public class OhjelmanNimi {
    private static Scanner input = new Scanner(System.in);

    public static void main(String[] args) {
	...
    }
}

Jokaisen Java-ohjelman osana on metodi main, joka on ohjelman tärkein metodi. Heti kun ohjelma käynnistyy, metodi main aloittaa toimintansa. Sitten kun metodi main päättyy, myös ohjelman suoritus päättyy.

Periaatteessa minkä tahansa ohjelman voisi kirjoittaa kokonaan main-metodiin, mutta suurista ohjelmista tulisi hyvin sekavia tällä tavalla toteutettuina. Nyt onkin aika opetella tekemään omia metodeita vanhan tutun main-metodin tueksi.

Esimerkki

Seuraavassa ohjelmassa on oma metodi tulostaViesti:

import java.util.*;

public class ViestinTulostus {
    private static Scanner input = new Scanner(System.in);

    public static void tulostaViesti(String viesti) {
        System.out.println(viesti);
    }

    public static void main(String[] args) {
        tulostaViesti("Tervetuloa!");
        tulostaViesti("Kappas kippis!");
        tulostaViesti("Hei hei!");
    }
}

Ohjelman tulostus on seuraava:

Tervetuloa!
Kappas kippis!
Hei hei!

Metodin tulostaViesti tehtävänä on tulostaa sille annettu merkkijono. Ohjelma kutsuu metodia kolmesti antaen sille kolme eri viestiä. Metodin kutsussa suoritetaan metodin sisällä oleva koodi. Metodin päättymisen jälkeen ohjelman suoritus jatkaa kohdasta, jossa metodia kutsuttiin.

Metodin rakenne

Metodin alussa olevat sanat public static void saavat selityksen myöhemmin. Toistaiseksi meidän riittää tietää, että kaikki toimii, kun aloitamme metodimme näillä sanoilla.

Näiden jälkeen tulee kiinnostava asia eli metodin nimi. Tällä nimellä metodia voi kutsua muualta koodista. Yllä olevassa esimerkissä metodin nimi oli tulostaViesti.

Metodin parametrit ovat sulkeissa nimen jälkeen. Parametrien avulla metodille voi välittää tietoa muualta koodista. Jokaisesta parametrista ilmoitetaan tyyppi ja nimi. Yllä olevassa esimerkissä metodin parametrin tyyppi oli String ja nimi oli viesti. Parametrin avulla metodille annettiin tulostettava viesti.

Esimerkki: Viestin toistaminen

Laajennetaan edellistä esimerkkiä lisäämällä siihen uusi metodi toistaViesti:

import java.util.*;

public class ViestinTulostus {
    private static Scanner input = new Scanner(System.in);

    public static void tulostaViesti(String viesti) {
        System.out.println(viesti);
    }
    
    public static void toistaViesti(String viesti, int kerrat) {
        for (int i = 0; i < kerrat; i++) {
            tulostaViesti(viesti);
        }
    }

    public static void main(String[] args) {
        toistaViesti("Tervetuloa!", 3);
        toistaViesti("Kappas kippis!", 4);
        toistaViesti("Hei hei!", 2);
    }
}

Ohjelman tulostus on seuraava:

Tervetuloa!
Tervetuloa!
Tervetuloa!
Kappas kippis!
Kappas kippis!
Kappas kippis!
Kappas kippis!
Hei hei!
Hei hei!

Metodille toistaViesti annetaan kaksi parametria: tulostettava viesti ja toistokertojen määrä. Metodissa toistaViesti on silmukka, joka kutsuu edelleen metodia tulostaViesti.

Seuraava kuva havainnollistaa, kuinka ohjelma kutsuu metodeja:

Metodien hyödyt

Metodien käyttämisestä on kaksi hyötyä:

Palautusarvo

Metodin palautusarvo on arvo, jonka metodi palauttaa sen kutsukohtaan muualla koodissa.

Palautusarvon tyyppi merkitään metodin määrittelyssä metodin nimen eteen. Jos metodilla ei ole palautusarvoa, käytetään sanaa void. Muuten merkitään arvon tyyppi tavalliseen tapaan.

Metodi palauttaa arvon kutsukohtaan komennolla return.

Esimerkki

Seuraavassa ohjelmassa on kaksi arvon palauttavaa metodia:

import java.util.*;

public class ArvonPalautus {
    private static Scanner input = new Scanner(System.in);

    public static int tuplaa(int n) {
        return n * 2;
    }
    
    public static int suurempi(int a, int b) {
        if (a > b) {
            return a;
        } else {
            return b;
        }
    }

    public static void main(String[] args) {
        System.out.print("Anna luku: ");
        int luku = Integer.parseInt(input.nextLine());
        int tulos = tuplaa(luku);
        System.out.println("Tuplattu: " + tulos);

        System.out.println("Anna kaksi lukua:");
        int eka = Integer.parseInt(input.nextLine());
        int toka = Integer.parseInt(input.nextLine());
        System.out.println("Suurempi: " + suurempi(eka, toka));
    }
}

Ohjelman suoritus voi olla seuraava:

Anna luku: 3
Tuplattu: 6
Anna kaksi lukua:
2
5
Suurempi: 5

Metodille tuplaa annetaan luku, ja metodi palauttaa luvun kaksinkertaisena. Metodille suurempi annetaan kaksi lukua, ja metodi palauttaa luvuista suuremman.

Huomaa kaksi erilaista tapaa käyttää metodin palautusarvoa: sen voi sijoittaa muuttujaan tai suoraan tulostuskomennon osaksi.

Esimerkki: Merkkijonon kääntäminen

Seuraava metodi kääntää merkkijonon ympäri:

public static String kaanna(String merkkijono) {
    String tulos = "";
    for (int i = 0; i < merkkijono.length(); i++) {
        char merkki = merkkijono.charAt(i);
        tulos = merkki + tulos;
    }
    return tulos;
}

Metodia voi kutsua koodissa vaikkapa seuraavasti:

System.out.println(kaanna("esimerkki"));

Tämän koodin tulostus on seuraava:

ikkremise

Metodi muodostaa käännetyn merkkijonoon muuttujaan tulos. Se käy läpi merkkijonon merkit alusta loppuun ja lisää joka kerta merkin muuttujan tulos alkuun. Varmista vielä, että ymmärrät metodin toiminnan.

Esimerkki: Palindromin tarkistaminen

Merkkijono on palindromi, jos se on sama alusta loppuun ja lopusta alkuun luettuna. Esimerkiksi merkkijono "saippuakauppias" on palindromi. Seuraava metodi tarkistaa, onko merkkijono palindromi:

public static boolean palindromi(String merkkijono) {
    return merkkijono.equals(kaanna(merkkijono));
}

Metodia voi käyttää koodissa seuraavasti:

System.out.println("Anna sana: ");
String sana = input.nextLine();
if (palindromi(sana)) {
    System.out.println("Sana on palindromi.");
} else {
    System.out.println("Sana ei ole palindromi.");
}

Ohjelman suoritus voi olla seuraava:

Anna sana: enne
Sana on palindromi.

Metodi palindromi palauttaa arvon true, jos merkkijono on palindromi, ja muuten arvon false. Metodi vertaa keskenään kahta asiaa: alkuperäistä merkkijonoa ja metodin kaanna tuottamaa käännettyä merkkijonoa. Metodin equals palauttama totuusarvo soveltuu sellaisenaan palautusarvoksi.

Metodin lopettaminen

Komento return lopettaa metodin suorituksen välittömästi, vaikka se olisi keskellä metodia. Komentoa voi käyttää myös silloin, kun metodi ei palauta arvoa. Silloin komennon ainoa vaikutus on, että metodin suoritus päättyy.

Esimerkki: Onko negatiivista lukua?

Seuraava metodi tarkistaa, onko listalla negatiivista lukua:

public static boolean onNegatiivinen(ArrayList<Integer> lista) {
    for (int luku : lista) {
        if (luku < 0) {
            return true;
        }
    }
    return false;
}

Metodia voi käyttää koodissa seuraavasti:

ArrayList<Integer> luvut = new ArrayList<Integer>();
luvut.add(5);
luvut.add(9);
luvut.add(-4);
luvut.add(6);    
if (onNegatiivinen(luvut)) {
    System.out.println("Listalla on negatiivinen luku.");
} else {
    System.out.println("Listalla ei ole negatiivista lukua.");
}

Ohjelman tulostus on seuraava:

Listalla on negatiivinen luku.

Metodi onNegatiivinen käy läpi listalla olevia lukuja. Heti jos vastaan tulee negatiivinen luku, metodi palauttaa arvon true ja päättyy. Silmukan jälkeen metodi palauttaa arvon false, koska silloin listalla ei ollut negatiivista lukua.

Rekursiivinen metodi

Rekursiivinen metodi on siitä erikoinen, että se kutsuu itseään. Tyypillinen esimerkki rekursiivisesta metodista on kertoman laskeva metodi. Kokonaisluvun n kertoma n! tarkoittaa tuloa 1 · 2 · 3 · ... · n, eli esimerkiksi 5! = 1 · 2 · 3 · 4 · 5 = 120. Lisäksi on sovittu, että 0! = 1.

Seuraava rekursiivinen metodi laskee kertoman:

public static int kertoma(int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * kertoma(n - 1);
    }
}

Mieti, miten metodi saa laskettua esimerkiksi luvun 5 kertoman.

Olio-ohjelmointi

11. Olio-ohjelmointi

Olio

Olio muodostuu kahdesta asiasta:

Tähän mennessä olemme jo käyttäneet kahdenlaisia olioita:

String-oliot

String-olion tietosisältönä ovat merkkijonossa olevat merkit. Olion metodeja ovat mm. length, joka palauttaa merkkien määrän, sekä charAt, joka palauttaa tietyssä kohdassa olevan merkin.

ArrayList-oliot

ArrayList-olion tietosisältönä ovat listalla olevat arvot. Olion metodeja ovat mm. add, joka lisää uuden arvon listalle, sekä size, joka palauttaa listalla olevien arvojen määrän.

Luokka

Luokka kertoo, miten sitä vastaavat oliot rakentuvat. Tarkastellaan esimerkiksi seuraavia merkkijonoja:

Merkkijonot ovat erilaisia, mutta niissä on yhteistä se, että kaikissa on joukko merkkejä peräkkäin. String-luokka määrittelee tämän asian: jokainen String-olio sisältää joukon merkkejä peräkkäin.

Muuttujien tyypit

Javassa muuttujan tyyppi on joko alkeistyyppi tai viittaustyyppi.

Alkeistyyppi tarkoittaa, että muuttujaan tallennetaan suoraan sen arvo. Esimerkiksi int ja double ovat alkeistyyppejä.

Viittaustyyppi tarkoittaa, että muuttujaan tallennetaan viittaus olioon. Luokkaa vastaava muuttuja on viittaustyyppinen.

Tarkastellaan seuraavaa koodia:

String nimi = "Aapeli";
int ika = 31;

Tässä String on viittaustyyppi, kun taas int on alkeistyyppi, minkä vuoksi tilanne muistissa näyttää seuraavalta:

Arvo vs. viittaus

Seuraava koodi havainnollistaa arvon ja viittauksen eroa:

int luku1 = 5;
int luku2 = 12;

ArrayList<Integer> lista1 = new ArrayList<Integer>();
lista1.add(2);
lista1.add(7);
ArrayList<Integer> lista2 = new ArrayList<Integer>();
lista2.add(4);

System.out.println("luku1 = " + luku1 + ", luku2 = " + luku2);
System.out.println("lista1 = " + lista1 + ", lista2 = " + lista2);

luku1 = luku2;
lista1 = lista2;

System.out.println();
System.out.println("luku1 = " + luku1 + ", luku2 = " + luku2);
System.out.println("lista1 = " + lista1 + ", lista2 = " + lista2);

luku1 = 8;
lista2.add(5);

System.out.println();
System.out.println("luku1 = " + luku1 + ", luku2 = " + luku2);
System.out.println("lista1 = " + lista1 + ", lista2 = " + lista2);

Koodin tulostus on seuraava:

luku1 = 5, luku2 = 12
lista1 = [2, 7], lista2 = [4]

luku1 = 12, luku2 = 12
lista1 = [4], lista2 = [4]

luku1 = 8, luku2 = 12
lista1 = [4, 5], lista2 = [4, 5]

Seuraava kuva vastaa ensimmäistä tilannetta:

Toisessa tilanteessa tapahtuu seuraavaa:

Nyt muuttujilla luku1 ja luku2 on sama arvo, kun taas muuttujat lista1 ja lista2 alkavat viitata samaan olioon.

Kolmas tilanne on mielenkiintoisin:

Muuttujat lista1 ja lista2 viittaavat samaan olioon, joten kun olio muuttuu, muutos heijastuu kumpaankin muuttujaan.

Roskienkerääjä

Yllä olevissa kuvissa kannattaa myös huomata, että vaikka mikään muuttuja ei viittaa enää listaan [2, 7], se on silti edelleen muistissa.

Roskienkerääjä on Javan suoritusympäristön osa, jonka tehtävänä on poistaa muistista tarpeettomia olioita. Se ei välttämättä käy toimeen heti, kun viimeinen viittaus olioon katoaa, mutta ennemmin tai myöhemmin olion varaama tila vapautuu uuteen käyttöön.

Metodin parametrit

Arvon ja viittauksen ero näkyy myös metodin parametreissa. Jos parametri on alkeistyyppinen, metodin muutokset siihen eivät välity kutsukohtaan. Jos taas parametri viittaa olioon ja metodi muuttaa oliota, muutos jää voimaan metodin suorituksen jälkeen.

Asiaa havainnollistaa seuraava metodi:

public static void testi(int luku, ArrayList<Integer> lista) {
    luku = 5;
    lista.add(8);
}

Käytetään metodia seuraavasti:

int luku = 3;
ArrayList<Integer> lista = new ArrayList<Integer>();
lista.add(4);
lista.add(7);
System.out.println("luku = " + luku + ", lista = " + lista);
testi(luku, lista);
System.out.println("luku = " + luku + ", lista = " + lista);

Koodin tulostus on seuraava:

luku = 3, lista = [4, 7]
luku = 3, lista = [4, 7, 8]

Vaikka metodi asetti parametrille luku uuden arvon 5, kutsukohdassa arvo 3 säilyy ennallaan. Sen sijaan luku 8, jonka metodi lisää parametrin lista viittaamaan listaan, ilmestyy myös kutsukohtaan.

Tyhjä viittaus

Javassa on myös mahdollista ilmaista, että viittaustyyppinen muuttuja ei viittaa mihinkään olioon. Tällöin muuttujan arvona on null.

Oma olio

Olio-ohjelmointi kuuluu pääasiassa Ohjelmoinnin jatkokurssin asioihin. Jo tässä vaiheessa on kuitenkin paikallaan vilkaista, miltä itse tehty olio näyttää. Teemme luokan Opiskelija, jota vastaavat oliot pitävät sisällään yhden opiskelijan tiedot.

Esimerkin testaamiseksi voit luoda uuden NetBeans-projektin, jonka nimeksi tulee OpiskelijaTesti. Saat projektiin uuden luokan valitsemalla File -> New File ja kirjoittamalla kohtaan Class Name luokan nimeksi Opiskelija.

Luokan Opiskelija koodi on seuraava:

public class Opiskelija {
    private String nimi;
    private int opintopisteet;

    public Opiskelija(String nimi, int opintopisteet) {
	this.nimi = nimi;
	this.opintopisteet = opintopisteet;
    }

    public void opiskele() {
	opintopisteet++;
    }

    public String toString() {
	return nimi + " (" + opintopisteet + " op)";
    }    
}

Seuraava ohjelma esittelee luokan käyttöä:

public class OpiskelijaTesti {
    public static void main(String[] args) {
	Opiskelija aapeli = new Opiskelija("Aapeli", 115);
	Opiskelija maija = new Opiskelija("Maija", 209);

	System.out.println("Opiskelijat:");
	System.out.println(aapeli);
	System.out.println(maija);

	aapeli.opiskele();
	aapeli.opiskele();
	maija.opiskele();

	System.out.println("Opiskelijat:");
	System.out.println(aapeli);
	System.out.println(maija);
    }
}

Ohjelman tulostus on seuraava:

Opiskelijat:
Aapeli (115 op)
Maija (209 op)
Opiskelijat:
Aapeli (117 op)
Maija (210 op)

Tarkastellaan osissa luokan Opiskelija rakennetta:

Tässä vaiheessa riittää, että saat suoritettua esimerkin ja ymmärrät suurin piirtein, mitä siinä tapahtuu. Palaamme asiaan tarkemmin Ohjelmoinnin jatkokurssilla.

Taulukko

12. Taulukko

Taulukko

Ennen vanhaan ohjelmointikielissä ei tavallisesti ollut ArrayListin kaltaista näppärää tietorakennetta. Tyypillinen ainoa tietorakenne oli taulukko, joka on myös Javan perustietorakenne.

Taulukko muistuttaa ArrayList-rakennetta, mutta sen käyttämiseen liittyvät seuraavat erot:

Taulukko näyttää ensisilmäyksellä rajoittuneelta, mutta taitava ohjelmoija pystyy toteuttamaan sen avulla minkä tahansa tietorakenteen. Myös ArrayList on toteutettu sisäisesti taulukon avulla.

Taulukkoa ei tarvitse kovin usein Javassa, mutta siitä kannattaa silti olla tietoinen. Yksi syy on, että jotkin Javan kirjastoon kuuluvat metodit käyttävät taulukoita. Lisäksi ohjelmoijan sivistykseen kuuluu tietää, miten erilaiset asiat voisi tehdä taulukolla, vaikka käytännössä yleensä voikin turvautua Javan kehittyneempiin tietorakenteisiin.

Taulukon määrittely

Seuraava koodi määrittelee taulukon, johon voi tallentaa 10 lukua:

int[] taulukko = new int[10];

Muunlaiset taulukot määritellään vastaavasti. Toisin kuin ArrayListin määrittelyssä taulukossa käytetään tavallisia muuttujatyyppejä.

Taulukon voi myös määritellä antamalla suoraan sen sisällön:

int[] taulukko = {4, 8, 3, 2, 9};

Yllä oleva koodi määrittelee taulukon, jossa ovat annetut viisi lukua.

Taulukon käyttäminen

Taulukon arvot on numeroitu nollasta alkaen samaan tapaan kuin ArrayListin arvot. Esimerkiksi äsken määritelty taulukko on muistissa seuraavasti:

kohta01234
arvo48329

Taulukon arvoihin viitataan antamalla taulukon nimi ja hakasulkeissa haluttu kohta taulukossa.

Seuraava koodi tulostaa taulukon toisen arvon:

System.out.println(taulukko[1]);

Seuraava koodi muuttaa taulukon kolmanneksi arvoksi luvun 6:

taulukko[2] = 6;

Taulukon läpikäynti

Perinteinen tapa käydä taulukko läpi on seuraava:

int[] taulukko = {4, 8, 3, 2, 9};
for (int i = 0; i < taulukko.length; i++) {
    System.out.println(taulukko[i]);
}

Ohjelman tulostus on seuraava:

4
8
3
2
9

Javassa on mahdollista käyttää myös samanlaista for-silmukkaa kuin ArrayListin läpikäynnissä:

int[] taulukko = {4, 8, 3, 2, 9};
for (int luku : taulukko) {
    System.out.println(luku);
}

Taulukosta etsiminen

Suoraviivainen tapa etsiä arvoa taulukosta on käydä taulukko läpi for-silmukalla ja katsoa, esiintyykö arvo jossain kohtaa taulukkoa. Tällaisen etsintätavan nimi on peräkkäishaku. Koodi ei ole vaikea:

public static boolean perakkaishaku(int[] taulukko, int haettava) {
    for (int luku : taulukko) {
	if (luku == haettava) {
	    return true;
	}
    }
    return false;
}

Taulukon järjestäminen

Miten taulukon voisi järjestää kotikonstein?

Yksi yksinkertainen tapa järjestää taulukko on kuplajärjestäminen. Siinä taulukkoa käydään toistuvasti läpi ja jos jossain kohtaa kaksi vierekkäistä arvoa on väärin päin, niiden järjestys korjataan. Järjestäminen on valmis, kun läpikäynnin aikana ei tarvitse muuttaa mitään.

Kuplajärjestämisen voi toteuttaa seuraavasti:

public static void jarjestaminen(int[] taulukko) {
    boolean eiValmis = true;
    while (eiValmis) {
        eiValmis = false;
        for (int i = 0; i < taulukko.length - 1; i++) {
	    if (taulukko[i] > taulukko[i + 1]) {
	        int vaihto = taulukko[i];
	        taulukko[i] = taulukko[i + 1];
	        taulukko[i + 1] = vaihto;
	        eiValmis = true;
	    }
        }
    }
}

Tässä on esimerkki kuplajärjestämisen toiminnasta:

  4<->8   3   2   9
   
  4   3<->8   2   9

  4   3   2<->8   9

  4   3   2   8<->9

  3<->4   2   8   9

  3   2<->4   8   9

  3   2   4<->8   9

  3   2   4   8<->9

  2<->3   4   8   9

  2   3<->4   8   9

  2   3   4<->8   9

  2   3   4   8<->9
    

Binäärihaku

Jos taulukko on järjestyksessä, sieltä etsimisen voi toteuttaa todella tehokkaasti. Binäärihaku jakaa joka vaiheessa etsintäalueen kahteen yhtä suureen osaan ja katsoo osien välissä olevasta arvosta, kumpaan suuntaan hakua tulee jatkaa. Jos mietit nimen etsimistä puhelinluettelosta, saat hyvän idean binäärihaun toiminnasta.

Binäärihaun idean voi kuvata helposti, mutta algoritmin toteuttaminen täysin toimivaksi on vaikeaa. Seuraavassa on yksi yritys:

public static boolean binaarihaku(int[] taulukko, int haettava) {
    int vasen = 0;
    int oikea = taulukko.length - 1;
    boolean onTaulukossa = false;
    while (vasen <= oikea) {
        int keski = (vasen + oikea) / 2;
        if (taulukko[keski] == haettava) {
            return true;
        }
        if (taulukko[keski] < haettava) {
            vasen = keski + 1;
        } else {
            oikea = keski - 1;
        }
    }
    return false;
}

Seuraavassa esimerkissä taulukosta haetaan lukua 10. Merkit v, k ja o tarkoittavat vastaavasti muuttujia vasen, keski ja oikea.

  3  5  8  9 10 12 16 17 19 25 27 30 34
  v                 k                 o

  3  5  8  9 10 12 16 17 19 25 27 30 34
  v     k        o                    

  3  5  8  9 10 12 16 17 19 25 27 30 34
           v  k  o