::: toc @toc :::
Tere,
Kui soovid programmeerijaks õppida, oled õiges kohas. Käesolevad materjalid on loodud IT Kolledži tarbeks, aga siht on võimaldada igaühel programmeerimist õppida põhjalikult. Materjalid pole veel valmis, aga võid juba proovida kuidas hammas peale hakkab ja tagasiside kirjuta foorumisse.
Meie ühine vestlus platvorm küsimuste ja muu teemakohase loba jaoks on kommuun.koodikool.ee.
Krister
25 september - Sissejuhatav loeng 7 oktoober - 1. projekti vaheetapp 8 oktoober - Praktikum 28 oktoober - 2. projekti vaheetapp 29-30 oktoober - Praktikum 20 november - Praktikum 11 detsember - Praktikum 7-8 jaanuar - Projekti vastamine 27-28 jaanuar - Kordamine 29 jaanuar - Eksam
Umbes kuu aega pärast eksamit tuleb üks ja ainus kordussooritus.
- 60 punkti tuleb projekti eest
- 5p esimesest vaheetapist
- 10p teisest vaheetapist
- 45p kaitsmisest
- 40 punkti eksami eest
- Lävend 50%
- Kui < 50%, siis on kogu aine 0
- 10 lisapunkti
- 1p kommuunis küsimuse küsimise eest
- 1-10p käesoleva lehe täiendmaine
Projekt on kõige tähtsam asi selle aine juures. Projekt on see, millega peaksid koguaeg tegelema. See annab reaalse kogemuse reaalsete probleemidega ja on ühtlasi ka kõige huvitavam viis asi selgeks saada.
Et ikka põnev oleks saad päris oma programmi kirjutada. Ära idee leidmise pärast liialt vaeva näe. Kui endal pähe ei tule siis leia mõni olemasolev programm ja matki see järgi. Võib teha ka mängu.
Point on ennast proovile panna. Siis on huvitav ja siis õpib. Ma ei mõtle, et peaksid nüüd päeva pealt profiks hakkama, aga võta ikka mõnuga. Siin tuleb täheldada seda, et kui teed lihtsa idee ära, siis seda saab alati keerulisemaks täiendada - lihtne on hea. Ühtlasi peaks keerulisele programmile lähenema tema kõige lihtsamast küljest ja siis vaikselt täiendama - keeruline on ka hea. Lühidalt - võta mingi idee ja hakka pihta!
Projekti mahtu on väga raske hinnata. Asi on selles, et kui algaja kirjutab 1000 rida koodi probleemi lahendamiseks, siis edasijõudnud teeb sama asja 100 reaga ära. See ei ole kirjand ja koodi koguse järgi projekti kvaliteeti hinnata ei saa. Küll aga annab hindamise kriteerium sulle aimu, milliseid tehnilisi lahendusi tähele pannakse hindamisel.
Kõik on hästi. Kui sa kujundad oma programmi paberil ära, mõtled läbi mis funktsionaalsus sinna tuleb on juba esimene samm tehtud. Nüüd. Kui sul on i200 videod vaadatud, äkki isegi codecademy.com mõni Pythoni kursus tehtud, siis peaksid oskama Javas kõige lihtsamaid manöövreid teha: arvutada, kasutajalt sisendit küsida, tulemus välja printida. Kas sinu (ükskõik kui keerulist) programmi annab konsoolis ära teha mingil elementaarsel tasemel? Ehk tee kõige lihtsam variant kohe ära. Kui midagi juurde õpid saad täiendada ja kindlasti ära karda nullist uuesti kirjutamist, see arendabki tegelikult kõige rohkem.
Nagu iga õige projekt (näiteks lõputöö) tuleb projekt kaitsta kõigi ees. Esitamisel võid kasutada kooli arvutit, aga enda masinast on ikka kõige kindlam.
Esinemine näeb välja midagi sellist:
- Jaga oma giti repo publikuga
- Pane programm käima [2min]
- Selgita ühte koodijuppi, mille üle oled eriti uhke [2min]
- Publiku küsimused ja õppejõu tagasiside koos hindega [2min]
Nonii. "Ükskõik kui keeruline või lihtne" on tore, aga mille eest reaalselt hinde saab? Siin on siis täpne hindamise kriteerium. Boldis punktid on hädavajalikud ja ilma nendeta hinnet ei saa.
- Kood on gitis, õppejõud saab ligi.
- Võõras kood on allikale viidatud
- Programmi sisu
- Programm käivitub
- Kasutajaliidese olemasolu
- Puugid ei takista protsessi
- Projekti kirjeldus failis README.md (.md on markdown)
- Nimi
- Projekti kirjeldus
- Kasutusjuhend
- Litsents
- Lihtne lugeda
- kood ei ole spagetistunud
- muutujate, meetodite jm. nimetused on mõistetavad
- selguse tagamiseks on koodi kommenteeritud
- Optimaalne ja taaskasutatav ülesehitus
- kasutab objekt-orienteeritust
- koodis ei ole ülearu kordusi
- Kood on kompaktne (lisapunktid, kui on näha erilist läbimõeldust)
- keerulised tsüklid
- rekursioon
- eriti hea klasside/meetodite taaskasutatavus
- Lisapunkte
- Tudeng on läinud aine raamistikust edasi, ehk oskab rohkem kui on aines õpetatud.
- Tudeng on reaalselt gitti kasutanud (committide periood on loogiline)
- Kasutatud on lisa raamistikke, näiteks SQL andmebaas.
- Kui tudeng tööga päris valmis ei saanud, kas ta vähemalt teab mida järgmiseks peaks tegema?
(Rakendada ainult kui väga vaja, eksam on lõplik filter)
- Oskab selgitada suvalist kohta koodis.
- Oskab programmi käiku muuta, kui õppejõud seda palub.
- Oskab käigu pealt tsükleid valmistada.
- Hilinejaid sisse ei lubata.
- Eksam toimub klassi arvutis.
- Telefoni ei näpi. Nimelt on kooli arvuti ainuke ekraan sinu elus.
- Ei tohi kellegagi suhelda ei netis ega mujal v.a. õppejõuga.
- Arvesse läheb ainult esimene giti link - valida ei saa.
- Tohid kasutada internetti k.a. Google.
- Üleüldised sohi tegemise reeglid kehtivad (nt. naabrilt maha kirjutamine).
- Kõik ülesanded peavad olema lahendatud kasutades päris programmeerimise võtteid ja mitte lihtsalt näilisi lahendusi kirjutades.
- Aega on 3 tundi.
- Kui oled valmis lae lahendused üles samasse reposse kust nad said. Kui laed GitHubi või mujale avalikku kohta on tegu plagiaadi kaasa aitamises. Lahendusi võid jagada märtsis, kui kõik eksamid on ära olnud.
- Kui koodi pushimine gitiga ei õnnestu siis saada failid kokku pakitult (zip/rar/tar) mulle meilile: [email protected]. Kaasneb 5p penalt. Copy-paste koodi ma vastu ei võta.
- Õppejõud ei kontrolli, kas su töö läks gitti üles. Seda saad ise teha.
- Küsimusi võib küsida, aga tõenäoliselt oled ise midagi valesti teinud :)
- Tule klassi palju varem ja kinnita, et Intellij on seadistatud.
- Kui ülesanne on üle jõu siis lihtsusta enda jaoks, aga ära jäta programmi katki.
- Ära copy-paste! Ülesanded on piisavalt lihtsad, et ajavõitu ei ole. Aga kui sa ei tea täpselt mis teed siis nüüd kaotad aega.
- Ära kiirusta, mõtle läbi. Alati on lihtsam ja kergem lahendus olemas.
- Kui googeldad, siis ära otsi lahendusi ülesandele vaid vastuseid oma küsimustele!
Igaühel on oma viis õppimiseks, seega siin on hea nimekiri erinevatest online ressurssidest.
Paljud materjalid on hoopis Pythoni kesksed. See on väga hea. Python on hea algaja keel, millelt on lihtne Java peale ümber tulla.
- Bucky Roberts Üks tudengi lemmik
- Udemy väga hea kursus
- Stanfordi ülipopulaarne kursus
- Java Programming - Step by Step
- [Why is programming hard?https://youtu.be/BRaBWIcAqlQ
- PluralSight
- Coursera
- Khan Academy
- TurtleAcademy õpetab lihtsaid asju eriti loomulikul moel.
- Hour of Code
- CodeCademy
- CodeCombat
- Programming Basics
- CodingGame
- Objektorienteeritusest
- JavaNotes
- MetsHein (eesti keeles)
- Tartu Ülikooli "Programmeerimisest maalähedaselt"
- The 5 basic concepts of any programming language
- Learn without stress
- TutorialsPoint
- Head First Java
- Learn Java the Hard Way
On mõned põhitõed, mida enne päris maailmas tegutsemist tavaliselt ei õpi. Siin on kiire ülevaade.
- Programmeerimine on katse-eksitus meetodi maailm, ehk seda teevad nii algajad kui ka profid. Seega proovi ja katseta. Tee vigu, arvuti sinust ei tüdine. Kui lõpuks midagi tööle saad on võit tööd väärt.
- Ära karda programmi uuesti kirjutamist. Iga ümberkirjutamisega tuleb sul parem arusaam, kuidas asi tegelikult peaks olema. Alguses proovi lihtsalt midagi tööle saada.
- Kolmandal ümberkirjutamisel on sul juba päris hea programm.
- Google on progeja parim sõber. Internet on suur teadmiste pank ja pole kedagi, kes kõike peast teaks. Kuid tark ei kopeeri pimesi koodi vaid õpib seda mõistma ja kasutab vaid vajalike osi.
- Iga programm võtab kordades rohkem aega kui oskasid arvata. Optimism on elukutsega kaasnev oht.
- Efektiivse programmi loomine algab korralikust eeltööst. Pea ees sisse hüpates saad katsetada ja mängida, aga mitte midagi tõsist teha. Läbi on vaja mõelda nii otstarve, funktsionaalsus, kujundus kui ka programmi enda arhitektuur.
- Juunior / arendaja / Senior on kolm tiitlit, mida võid omistada. Juunior on muidugi õpilane. "Arendaja" oled siis, kui saad iseseisvalt hakkama ja seneioril on kuskil 7 aastat kogemust ja oskab ka kõige keerulisemaid probleeme lahendada. Kuskil seda kirjas muidugi ei ole ja antud kirjeldus on vaid mulje.
- Arvuti ei tee vigu. Inimesed teevad vigu. Inimene oled sina, olen mina ja on kõik need, kes on Java ja kõik muu tarkvara kirjutanud. Aga enne kui teisi süüdistad, tee 100% kindlaks, et viga pole sinu enda koodis.
- Tarkvara arendaja on küll ainus meeskonnaliige, kes on hädavajalik, et tarkvara toode valmis saada, aga ta kindlasti pole ainuke oluline. Et tootest asja saaks on vaja disaini, äri, arhitektuuri, kasutajatoe ja muid inimesi.
Aine peatükid avalduvad http://kommuun.koodikool.ee foorumis.
Java 8 saad alla laadida ja installida siit.
On soovitatav kasutada ametlikku Oracle JDK (üleval olev link) ja mitte OpenJDK, sest JavaFX ei ole OpenJDK's koheselt sees ja selle lisamine võib olla päris problemaatiline.
Intellij saad alla laadida ja installida siit.
Ennekõike on Intellij lihtne tekstiredaktor. Tal on palju kiirteesid (allpool räägime veel) ja muid võimalusi. Räägime kõige tähtsamast.
Esmane käivitus võib olla vähe keeruline - järgime piltidega õpetust siin.
Programmi käivitamiseks on lihtne otsetee ctrl + shift + f10
. Kui oled juba ühe korra käivitanud oma programmi, piisab ka lühemast ctrl + f10
otseteest. Vt. ka kiirklahve
Kui soovid näha kuidas täpselt su programm jookseb - rida rea haaval - siis Debug funktsioon on selle jaoks. Hoiatan, et erinevalt programmi tavapärane käivitamine võib see väga kaua aega võtta. Uuri lähemalt Debug videos.
Kui sul on failide vaade kadunud, leiad selle üles all-paremal olevast ikoonist.
Jumala kiirklahv on ctrl + shift + a, see on kõikide käskluste otsing.
ctrl + shift + a
Otsing: kõik Intellij käsklused
shift + f10
Käivita programm (olemasolevate seadetega)
ctrl + shift + f10
Käivita programm (loo uued seaded)
alt + enter
Paranda kursori all olev viga.
ctrl + shift + üles/alla
Viib kas rea või koodi jupi üles/alla
alt + j
Selekteeri järgmine identne koodijupp
shift + alt + click
Lisa veel üks kursor
shift + alt + insert
Muuda selekteerimine ploki kujuliseks
ctrl + click
Mine pärinevuse juurde.
ctrl + space
Autocomplete, ehk soovita midagi mis siia võiks sobida.
ctrl + w
Laienda selektsiooni
F2
Mine järgmise errori juurde.
ctrl + q
Loe kursori all oleva elemendi JavaDocsi.
ctrl + shift + enter
Lõpeta lause ja lisa semikoolon.
kirjuta käsk ja vajuta enter. Näiteks sout + enter
kirjutab System.out.println()
.
sout
System.out.println()
soutv
System.out.println("a = " + a)
psvm
public static void main()
fori
for (int i = 0; i < x; i++) {}
Kui täpitähed ei ilmu JavaFXis või konsoolis, siis on lahendus lihtne:
File -> Settings -> Editor -> File Encodings -> IDE ja Project Encoding peavad olema UTF-8 mõlemad.
Programmeerides võid kergesti hulluks minna ja üks põhilisi päästerõngaid on Git.
Git on versioonihaldussüsteem, mis teeb kolme asja eriti hästi:
- Hoiab tagavarakoopiaid pilves, juhul kui meie arvutiga peaks midagi juhtuma.
- Võimaldab tervel meeskonnal ühe programmiga samaaegselt toimetada
- Salvestab programmi staadiumeid, et kriitilise vea korral saab versioone tagasi kerida.
Giti kasutamine on lausa hädavajalik ja olen isiklikult näinud vaid ühte professionaalset arendajat, kes seda ei kasuta (pärast meie kohtumist kasutab). Muidugi on versioonihaldussüsteeme rohkemgi, kuid Git on vaieldamatult üks parimaid.
Gitiga võid hoida oma koodi ükskõik kus - meeskonna liikmete arvutites, oma serveris, mõnes pilveteenuses. Üks populaarsemaid pilveteenuseid avatud lähtekoodiga tarkvaral on GitHub.com.
Siin on mõned välised ressursid, mis aitavad teemat mõista:
- git-scm.com - sõbralik ja põhjalik ametlik dokumentatsioon.
- try.github.io - Interaktiivne õpetus.
- GitHub Youtube - Video õpetus.
- Roger Dudler - isetehtud õpetus.
- guides.github.com - GitHubi kasutamisest.
- Atlassian - Git, Tudeng soovitas.
Soovitan Gitti kasutada käsurealt, et seda mõista. On olemas ka kasutajaliidesega tarkvara, kuid algajale võib see eriti keeruliseks osutuda.
Muuda käesolev kaust Giti repositooriumiks
git init
Lae alla aadressil olev koodi repositoorium
git clone https://github.com/KristerV/javaHarjutused.git
Tõmba alla repositooriumi uuendused
git pull
Vaata üldist seisu
git status
Vaata mis koodi oled muutnud pärast viimast salvestatud seisu
git diff
Valmista üks fail ette salvestamiseks
git add path/to/file.java
Valmista kõik failid ette salvestamiseks
git add --all
Salvesta ettevalmistatud failid
git commit -m "lühikirjeldus tehtud muudatustest"
Lükka repositooriumi uuendused üles
git push
Vaata projekti ajalugu
git log
Tühista salvestamata muudatused
git checkout .
Kõiki faile ei ole meil vaja Gitti salvestada. Näiteks on Javas kompileeritud .class failid, millest pole hiljem kuigi palju kasu.
.gitignore on fail, millega saad faile ja kaustasid Giti eest ära peita.
Näiteks Java projekti puhul tahad salvestada src/ kausta, aga mitte out/ ega .idea/ kaustasid (.idea on Intellij konfiguratsioonid, millest sinu meeskonnakaaslastel on igaühel oma). Siis loo uus fail nimega .gitignore oma projekti algsess kausta järgneva sisuga:
out/
*.iml
.idea/
*.iml
ütleb veel lisaks, et me ei taha ühtegi faili salvestada, mis lõppeb .iml-iga.
Näitena võib tuua javaHarjutused repositooriumi.
Muutuja on sisuliselt nagu kast, kuhu saad ühe asja sisse panna. Sa pead ütlema kuidas kasti nimetada ja mis tüüpi asju sa sinna sisse tahad panna.
Näiteks kui soovime lapse vanust salvestada, siis sobib selleks int (integer, ehk täisarv) tüüp ja "mikuVanus" nimetus, siis Javas kirjutame seda järgnevalt:
int vanus = 5;
Kui sooviksin selle lapse nime salvestada, kasutaksin tüüpi String, ehk sõne:
String nimi = "Mikk";
Esimene oluline ohukoht
Igal arvu andmetüübil on oma miinimum ja maksimum võimalik arv, mida andmetüüp suudab hoida. Kui üritad maksimumi ületada, jätkab loendur teisest otsast. Näiteks int
andmetüübi maksimum on 2147483647:
int a = 2147483647;
int b = a + 1;
System.out.println("b = " + b); // b = -2147483648
Teine oluline ohukoht
Võtame lihtsa tehte: 2.0 - 1.1 = 0.9
. Ainult, et tegelikult tuleb Javas vastuseks 0.899999999999998. Kohati uskumatu, et selline viga on sees, aga see polegi üldse nii ebatavaline. Seda esineb ka teistes riistvaralähedastest keeltes. Lahenduseks on kas kasutada int tüüpi muutujaid (näiteks 23.34€ on 2334) või BigDecimal klassi arvutusteks.
väikesed arvud (alates -128 kuni 127)
Kasutamine
Loo uus
byte a = 25;
Liitmine
byte c = (byte) (34 + 3);
// (byte) on vajalik typecast, sest 34 ja 3 on algselt int tüüpi väärtused.
Võrdlemine
a == b;
Muuda tüüpi
double c = a;
täisarvud (alates -2'147'483'648 kuni 2'147'483'647)
Tõenäoliselt kasutame int tüüpi muutujaid arvudega tegeledes.
Kasutamine
Loo uus
int a = 5;
Matemaatika
a + b;
a - b;
a * b;
a / b;
(int) Math.pow(a, b); // a astmes b
Jagamine, Math.pow() ja muud arvutused võivad olla ebatäpsed, kuna int ei toeta komakohti.
Võrdlemine
a == b;
a != b;
a < b;
a <= b;
a > b;
a >= b;
Muuda tüüpi
double c = a;
reaalarvud (komakohaga) (alates -4.910^324 kuni 1.7910^308)
Reaalarvudega arvutamine on ebatäpne, vt. Ohukoht2
Kasutamine
Loo uus
double a = 8.76;
Matemaatika
a + b;
a - b;
a * b;
a / b;
Math.pow(a, b); // a astmes b
Võrdlemine
a == b;
a != b;
a < b;
a <= b;
a > b;
a >= b;
Muuda tüüpi
int c = (int) a;
typecast (int)
ei ümarda arve vaid raiub julmalt koma maha. double 8.76
on int 8
. Ümardamiseks kasuta Math.round()
.
kõik arvud (arvu suurust limiteerib vaid arvuti mälu)
BigDecimal on vajalik, et reaalarvudega täpseid arvutusi teha.
NB! Et arvutused oleksid täpsed, peavad arvud olema jutumärkides, ehk sõne kujul.
Kasutamine
Loo uus
BigDecimal a = new BigDecimal("2.00");
BigDecimal b = new BigDecimal("1.1");
Matemaatika
a.subtract(b); // a - b
a.add(b); // a + b
a.divide(b) // a / b (ohtlik!)
a.divide(b, 3, BigDecimal.ROUND_HALF_UP); // õige
a.multiply(b); // a * b
a.pow(3); // a astmel 3
a.divide() annab errori, kui ei saa täpselt arvutada. Tuleb kasutada formaati
a.divide(b, 3, BigDecimal.ROUND_HALF_UP)
, ehk
a.divide(jagaja, komakohti, ümardamise valem)
.
Võrdlemine
a.equals(b) // a == b
a.compareTo(b) // annab vastuseks -1, 0 või 1
// -1 (a < b)
// 0 (a == b)
// 1 (a > b)
Muuda tüüpi
int c = a.intValue();
double d = a.doubleValue();
üksik täht
Kindlasti kasuta ühekordseid jutumärke!
Kasutamine
Loo uus
char a = 'a';
Võrdlemine
'a' == 'b';
'a' != 'b';
'a' < 'b';
'a' > 'b';
'a' <= 'b';
'a' >= 'b';
Sõne, ehk jutumärkide vahele saab panna kõiki sümboleid
Kindlasti kasuta topelt jutumärke!
Kasutamine
Loo uus
String a = "Lähme õue mängima.";
Võrdlemine
a.equals(b)
Liitmine
"Tere, " + "hommikust" => "Tere, hommikust"
"Vanus: " + 45 => "Vanus: 45"
"Vanus: " + "45" => "Vanus: 45"
"45" + 5 => "455"
Tüübi muutmine
int c = Integer.parseInt(a);
double c = Double.parseDouble(a);
Kas sõne sisaldab "õue"
a.contains("õue");
Muuda kõik tähed suureks
a.toUpperCase();
Muuda kõik tähed väikseks
a.toLowerCase();
Poolita sõne tühikutega.
a.split(" ");
// ["Lähme", "õue", "mängima."]
Asenda "õue" sõnega "arvutisse"
a.replace("õue", "arvutisse");
// "Lähme arvutisse mängima."
Nagu replace(), aga regex'iga
a.replaceAll(regex, "uus väärtus");
Kas sõne on tühi?
a.isEmpty();
Mis indeksil on sõne "mängima"?
a.indexOf("mängima"); // 10
Mitu tähte on sõne pikk?
a.length(); // 18
Mis täht asub indeksil 0?
a.charAt(0); // 'L'
tõene või väär, ehk true
või false
.
Kasutamine
Loo uus
boolean a = true;
Võrdlemine
true == true;
true != false;
true == true && false == false;
true == false || false == false;
&&
on loogiline "ja", ehk mõlemad tingimused peavad olema tõesed.
||
on nagu "või", ehk üks tingimustest peab olema tõene.
||
ei ole LL, ega ii. ||
on "pipe" ehk AltGr + <
;
keerulisemad objektid.
ArrayList ja String on samuti objektid, aga siin pean silmas kõiki objekte. Need võivad tulla Java APIst või oled sa ise neid loonud.
Näiteks, kui tegin ise klassi Hobune:
public class Hobune {
int kaal = 500;
String nimi = "Hopsu";
public void ytleOmaNimi() {
System.out.println("H-H-H-Hopssuuuu..");
}
}
siis nüüd saan oma main meetodi sees luua "Hobune" klassist uue objekti ja kasutada tema public
meetoode.
public class MinuProgramm {
public static void main(String[] args) {
Hobune h = new Hobune(); // uus hobuse objekt
h.ytleOmaNimi(); // kasutan tema meetodi
System.out.println(h.kaal); // küsin välja hobuse kaalu
}
}
ja programm printis välja kaks sõnumit: "H-H-H-Hopssuuuu.." ja "500".
Kui andmete kogus suureneb oleks mõistlik saja muutuja asemel kasutada ühte nimekirja. Näiteks kui on spordivõistlused ja võistleja nr 1 tegi 10 katset. Siis 10 muutuja asemel saan öelda:
int[] võistleja1 = {76, 56, 75, 45, 56, 76, 65, 67, 45, 54};
Kujuta ette, kui võistlejaid on samuti kümme ja igaühel on 10 tulemust. Siis jällegi ei ole meil tarvis kümmet muutujat vaid ühte head HashMapi, mille sees on omakorda ArrayList:
HashMap tulemused = new HashMap(); // Loo HashMap
ArrayList voistleja = new ArrayList(); // Loo ArrayList
for (int i = 0; i < 10; i++) { // iga võistleja kohta
voistleja.clear(); // tühjenda eelnevad katsed
for (int j = 0; j < 10; j++) { // iga katse kohta
voistleja.add((int) (Math.random() * 100)); // genereeri katse tulemus
}
tulemused.put("võistleja"+i, voistleja); // salvesta tulemus
}
System.out.println("tulemused = " + tulemused);
Antud koodi on raske mõista, aga tulemuseks on ilus tabel:
tulemused = {
võistleja2 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja1 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja0 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja6 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja5 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja4 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja3 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja9 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja8 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54],
võistleja7 = [54, 17, 25, 16, 10, 98, 86, 92, 10, 54]
}
Kui mul on siis hiljem vaja näiteks võistleja nr 6 tulemust nr 7, siis küsin selle välja ühe reaga:
int t = (int) ((ArrayList) tulemused.get("võistleja6")).get(7);
See üks rida on muidugi suhteliselt keeruline, aga andmed on meil vähemalt struktureeritud ja korras.
Hoiab mitmeid väärtusi korraga, aga ainult ühte tüüpi ja kogust muuta ei saa.
- lihtne kasutada
-
nimekirja pikkust ei saa muuta pärast esimest kasutamist
-
hoiab ainult ühte andmetüüpi korraga
indeksi põhine (loendamine algab nullist)
Näide
Ettevalmistus
int[] a = new int[6];
a[0] = 9;
a[1] = 11;
a[5] = 54;
System.out.println(Arrays.toString(a));
Tulemus
[9, 11, 0, 0, 0, 54]
Kasutamine
Loo uus
int[] a = new int[6];
int[] a = {6, 3, 2, 7};
String[] a = new String[6];
String[] a = {"mina", "olen", "sõnede", "massiiv"};
Küsi väärtus indeksil 5
a[5]
Määra väärtus indeksil 5
a[5] = 8;
Nimekirja pikkus
a.length
Võrdlemine
Arrays.equals(a, b)
Sorteeri tähestikulises järjekorras
Arrays.sort(a)
Prindi välja
System.out.println(Arrays.toString(a))
Hoiab eri tüüpi väärtusi ja nimekirja pikkus muutub vastavalt sisule.
-
hoiab erinevaid andmetüüpe segamini
-
nimekirja pikkus muutub vastavalt sisule
- kasutamine on veidi keerulisem kui massiivi puhul
indeksi põhine (loendamine algab nullist)
Näide
Ettevalmistus
ArrayList a = new ArrayList();
a.add("Sõne");
a.add(54);
a.add(87.90);
System.out.println("a = " + a);
Tulemus
[Sõne, 54, 87.9]
Kasutamine
Loo uus
ArrayList a = new ArrayList();
ArrayList<String> a = new ArrayList();
ArrayList<Integer> a = new ArrayList();
Mis on indeksil
a.get(i)
Asenda indeksil i olev väärtus uue väärtusega b
a.set(i, b)
Lisa väärtus nimekirja lõppu
a.add(väärtus)
Eemalda väärtus
a.remove(väärtus)
Tühjenda nimekiri
a.clear()
Nimekirja pikkus
a.size()
Kas sisud on võrdsed?
a.equals(b)
Mis indeksil on väärtus?
a.indexOf(väärtus)
Sorteeri tähestiku järgi
Collections.sort(a)
Kas sisaldab väärtust?
a.contains(väärtus)
Prindi
System.out.println(a)
kas on tühi?
a.isEmpty()
Hoiab <võti, väärtus> andmeid.
- lihtsustab keeruliste andmete hoidmist
- keeruline kasutada
Siin ei ole indekseid, ehk ei ole ka võtmete järjekorda võimalik määrata.
Lihtsam näide <String, Integer> andmestruktuurist.
Ettevalmistus:
HashMap<String, Integer> a = new HashMap<>();
a.put("Peeter", 35);
a.put("Mari", 38);
a.put("Janika", 15);
a.put("Mikk", 3);
System.out.println("a = " + a);
Tulemus:
{
Peeter = 35,
Mikk = 3,
Janika = 15,
Mari = 38
}
Keerulisem näide <String, HashMap> andmestruktuurist.
Ettevalmistus:
HashMap<String, HashMap> a = new HashMap<>());
HashMap milvi_andmed = new HashMap();
HashMap laika_andmed = new HashMap();
milvi_andmed.put("vanus", 25);
milvi_andmed.put("elukoht", "Põlva");
laika_andmed.put("vanus", 66);
laika_andmed.put("elukoht", "Kosmos");
a.put("Milvi", milvi_andmed);
a.put("Laika", laika_andmed);
System.out.println("a = " + a);
Tulemus:
{
Laika = {
vanus = 66,
elukoht = Kosmos
},
Milvi = {
vanus = 25,
elukoht = Põlva
}
}
Kasutamine
Loo uus
HashMap a = new HashMap();
HashMap<String, Integer%gt; a = new HasMap<%gt;();
Mis väärtus on võtmel
a.get(võti)
Asenda väärtus võtmel või lisa uus võti-väärtus paar
a.put(võti, väärtus)
Eemalda võti koos väärtusega
a.remove(võti)
Tühjenda nimekiri
a.clear()
Nimekirja pikkus
a.size()
Kas sisud on võrdsed?
a.equals(b)
Kas võti on olemas
a.containsKey();
Kas väärtus on olemas
a.containsValue();
Prindi välja
System.out.println(a)
kas on tühi?
a.isEmpty()
Andmebaas on andmete hoidmise viis sarnaselt massiiv, ArrayList või HashMap. Vahe on nüüd selles, et andmebaasi andmed jäävad kõvakettale alles ka siis, kui su programm vahepeal sulgeb. Andmebaas on reeglina serveris täiesti eraldi seisev programm, lisaks sinu Java programmile. Aga et me ei peaks midagi seadistama võime projekti tarvis kasutada faili põhist lihtsat süsteemi nagu näiteks SQLite. Selle pead alla laadima ja installima. SQL on spetsiaalne andmebaasiga suhtlemise keel. Õnneks mitte väga keeruline. Andmebaasi käima saamine on aga ilma näidiseta paras piin.
Näidis kood koos seletustega on siin: Andmebaasi näidisprogramm
Kui võtame suvalise hunniku Java andmetüüpe [int, double, String, ArrayList], siis näeme, et osad on suure algustähtedega, osad on väiksega. See ei ole programmeerija suva järgi vaid tuleneb selle tüübi võimalustest. Näiteks int tüüpi muutuja on lihtsalt täisarv ja temaga ei saagi peale arvutamise midagi teha. String on aga sõne ja temaga saab igast pulli teha:
String nimi = "Krister"; // Teen uue muutuja
nimi = nimi.replace('r', 'l'); // muudan kõik 'r' tähed 'l' tähtedeks
System.out.println(nimi); // Nimi on nüüd "Klistel" - hahaha!
.replace() on meetod. Ja meetodid saavad ainult objektidel olla. Seega suure algustähega tüübid on objektid ja väikesega on primitiivid. Primitiivil ei ole meetoode ja objektidel on.
Juhtimisstruktuurid on programmeerija põhilised tööriistad, nagu ehitajal on haamer ja kruvikeeraja. Siin käsitleme kahte liiki: "kui" ja "kuni", ehk "kui" tingimus on täidetud käitu sedasi ja "kuni" tingimus on täidetud käitu sedasi. Muud neil vahet polegi, kui ühed juhivad programmi kulgemist vaid ühe korra ja teised panevad ühe koodi jupi tsükliliselt kordama.
"Kui" tüüpi valikud on if
, switch
ja try-catch
. "Kuni" tüüpi tsüklid on while
, for
, for each
ja do..while
.
if on nagu raudtee hargnemine. Üks tee läheb Tartu poole, teine Viljandi. if lausega saab rongi (ehk programmi) vastavalt sihtpunktile juhatada õigele teele.
Vt. ka kuidas booleane võrrelda
Point
Teha programmis lihtsaid valikuid (==, !=, <=, >=, string.equals())
Süntaks
if (tingimus) {
tegevus
} else {
alternatiivne tegevus
}
Näite ülesanne
Kui punkte on 50 või rohkem, saab tudeng ainest läbi. Kui on vähem, siis ei saa.
Lahendus koodis
int punkte = 55;
if (punkte >= 50) {
System.out.println("tudeng sai ainest läbi");
} else {
System.out.println("tudeng ei saanud ainest läbi");
}
Point
Teha paljude variantidega, aga lihtsama tingimusega (ainult ==), valikuid.
Süntaks
switch (muutuja) {
case väärtus1:
tegevus1;
break;
case väärtus2: // kasuta järgneva väärtuse tegevust
case väärtus3:
tegevus3;
break;
case väärtus4:
tegevus4;
break;
}
Näite ülesanne
Järgmise aasta ilmateade: kui on suvi, paistab päike; kui on talv, sajab lund, kevadel ja sügisel sajab vihma.
Lahendus koodis
String aastaaeg = "kevad";
switch (aastaaeg) {
case "talv":
System.out.println("Sajab lund");
break;
case "suvi":
System.out.println("Päike");
break;
case "kevad": // kevade ja sügise tulemus on sama
case "sügis":
System.out.println("Sajab vihma");
break;
}
Point
Try-catch on nagu if-else, ainult, et on mõeldud veaohtlike koodijuppidele.
Näite ülesanne
Loe kõvakettalt fail üles, kui millegipärast toiming ebaõnnestub, anna sellest teada.
Lahendus koodis
BufferedReader br;
try {
br = new BufferedReader(new FileReader("file.txt"));
} catch (FileNotFoundException e) {
System.out.println("Faili ei loetud, sest:");
e.printStackTrace(); // prindib detailse errori
}
Kui programmil on vaja nüüd mitte lihtsalt hargneda (otsus langetada) vaid ühte koodijuppi käiata kümneid või isegi tuhandeid kordi, siis on tsüklid selle jaoks. While tsükkel on selles mõttes universaalne, et sellega saab kõike teha, mida teistegagi. Teiste tsüklite mõte on lihtsustada kindlaid igapäevaseid toiminguid. Näiteks kui sul on vaja just numbritega mängida, siis saad for tsükliga kiiremini asja tehtud. Kui soovid massiivi väärtustega tegeleda, on 'for each' ideaalne.
Point
Korrata koodi kuni tingimus on tõene
Ül1: prindi numbrite jada 1-10
int count = 0;
while (count < 10) {
System.out.println(count + 1);
count = count + 1;
}
Ül2: Prindi välja väärtused massiivist
String[] m = {
"olen",
"lihtne",
"ülesanne"
};
int count = 0;
while (count < m.length) {
System.out.println(m[count]);
count = count + 1;
}
Point
Identne while tsükliga, aga käiatakse vähemalt ühe korra, sest tingimuse kontrollimine toimub lõpus.
Ül1: prindi numbrite jada 1-10
int count = 0;
do {
System.out.println(count + 1);
count = count + 1;
} while (count < 10);
Ül2: Prindi välja väärtused massiivist
String[] m = {
"olen",
"lihtne",
"ülesanne"
};
int count = 0;
do {
System.out.println(m[count]);
count = count + 1;
} while (count < m.length);
Point
Korrata koodi x arv kordi
Ül1: prindi numbrite jada 1-10
for (int i = 0; i < 10; i++) {
System.out.println(i + 1);
}
Ül2: Prindi välja väärtused massiivist
String[] m = {
"olen",
"lihtne",
"ülesanne"
};
for (int i = 0; i < m.length; i++) {
System.out.println(m[i]);
}
Point
Käia tsükliga läbi mõni andmete kogum (nt. massiiv)
Ül2: Prindi välja väärtused massiivist
String[] m = {
"olen",
"lihtne",
"ülesanne"
};
for (String s : m) {
System.out.println(s);
}
API on programmeerimises nagu veduril on kangid ja seierid. API ei ole mitte kasutajaliides, vaid programmiliides. Java API on sisuliselt valmis kirjutatud abilised. Näiteks, kui sul on vaja panna number 5 astmesse 7, siis käsitsi arvutamise asemel kasuta Math klassi meetodi pow():
Math.pow(5, 7);
Matemaatika on muidugi kõige lihtsam näide. Java API kaudu saab ka ligi kasutaja klaviatuurile, konsooli printimisele, faili toimingutele ja muudele vahenditele, mida muidu peaks ise välja mõtlema.
vt. kuidas kasutatakse Scanner objekti
System.out võimaldab meil infot kasutajale näidata. Kõige tavalisem käsk on System.out.println("Tere")
ja see näitab kasutajale konsoolis teksti "Tere".
print() kirjutab konsooli kõik väärtused järjest.
Näide
int vanus = 5;
String nimi = "Miku";
System.out.print("Minu nimi on " + nimi);
System.out.print(" ja ");
System.out.print("olen " + vanus + " aastat vana.");
Tulemus:
Minu nimi on Miku ja olen 5 aastat vana.
Lühend 'ln' tähendab 'line' meetodist println(). See trükib konsooli oma kirje ja alustab uue reaga.
Näide:
int vanus = 5;
String nimi = "Miku";
System.out.println("Minu nimi on " + nimi);
System.out.println(" ja ");
System.out.println("olen " + vanus + " aastat vana.");
Tulemus:
Minu nimi on Miku
ja
olen 5 aastat vana.
Lühend 'f' tähendab 'format' meetodis printf(). See meetod on eriti paindlik ja annab kujundamiseks erilisi võimalusi. Eriti mugav on seda kasutada, kui esineb palju muutujaid.
Et muutujaid kasutada, kasuta süntaksit printf(sõne, muutuja, muutuja, ...). Sõne sisse paned spetsiaalsed märgised (%s, %d, %n), et printf() teaks kuhu muutujad sisestada.
Näide
int vanus = 5;
String nimi = "Miku";
System.out.printf("Minu nimi on %s ja olen %d aastat vana.", nimi, vanus);
tulemus:
Minu nimi on Miku ja olen 5 aastat vana.
Võimalused
%s
String, ehk sõne
String nimi = "Peeter";
System.out.printf("Tere, %s, võta istet.", nimi)
// Tere, Peeter, võta istet.
%d
int, ehk täisarv
int yhendus = 4;
System.out.printf("Mul on %dG ühendus!", yhendus)
// Mul on 4G ühendus!
%f
float või double, ehk reaalarv
double pappi = 64.55;
System.out.printf("Saan %.2f euroga Berliini.", pappi);
// Saan 64.55 euroga Berliini.
'.2' käsib näidata vaid kahte komakohta.
%n
Uus rida
System.out.printf("Tere%nuus%nmaailm!");
// Tere
// uus
// maailm!
Math klass lihtsustab teatud matemaatilisi toiminguid.
Tagastab arvu absoluutväärtuse.
Math.abs(5); // 5
Math.abs(-5); // 5
Valib kahest arvust väiksema.
Math.min(1, 5); // 1
Math.min(89, 6); // 6
Valib kahest arvust suurema.
Math.max(1, 5); // 5
Math.max(89, 6); // 89
Astendab esimese arvu teisega.
Math.pow(2, 5); // 32.0
Math.pow(4, 8); // 65536.0
Genereerib suvalise numbri vahemikus 0-0.999999999.
Genereeri arv nullist 0.99999ni
Math.random()
Genereeri kas null või üks.
(int) (Math.random() * 2)
Genereeri täisarv arv nullist 99ni
(int) (Math.random() * 100)
Genereeri reaalarv 30st 40ni.
30 + Math.random() * 10
Ümardaja
Math.round(45.5876); // 46
Integer või int kõige väiksem võimalik värtus. Vaata ka Ohukoht1
Integer.MIN_VALUE; // -2147483648
Integer või int kõige suurem võimalik värtus. Vaata ka Ohukoht1
Integer.MAX_VALUE; // 2147483647
Kui sul on arv sõne kujul "25", siis parseInt muudab selle int'iks.
int a = Integer.parseInt("25");
Double või double kõige väiksem võimalik värtus. Vaata ka Ohukoht1
Double.MIN_VALUE; // -2147483648
Double või double kõige suurem võimalik värtus. Vaata ka Ohukoht1
Double.MAX_VALUE; // 2147483647
Kui sul on arv sõne kujul "33.333", siis parseDouble muudab selle double'iks.
double a = Double.parseInt("33.333");
Failide manipuleerimiseks on Javas palju viise. File, FileReaderi ja FileWriteri kasutamine on aga üks puisemaid ja lihtsasti arusaadavaid.
File klass on selleks, et fail programmi tuua.
FileReader on selleks, et faili sisu lugeda.
FileWriter on selleks, et faili sisu muuta.
Kasutamine
Loo uus File objekt.
File f = new File("tekst.txt");
Loo uus fail kettale.
f.createNewFile();
Kustuta fail kettalt.
f.delete();
Võrdle kahe faili sisu.
f.equals(f2);
Kas fail eksisteerib kettal?
f.exists();
File f = new File("tekst.txt");
FileWriter writer = new FileWriter(f);
writer.write("Rida üks\n");
writer.write("Rida kaks\n");
writer.write("Rida kolm\n");
writer.close();
File f = new File("tekst.txt");
BufferedReader br = new BufferedReader(new FileReader(f));
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
br.close();
JSON on mõnus üldlevinud failiformaat, mida on lihtne mõista ja kasutada. Pärit on ta JavaScript maailmast, aga Javas on selle kasutamine ka täiesti mõistlik juhul, kui on tarvis programmis mingeid andmeid sisse tuua.
Teeme siis näite läbi. Alustame sellest, et meil on fail dpd.json:
[
{
"kg": 0.5,
"estonia": {
"zone1": 4.27,
"zone2": 4.79
},
"latvia": {
"zone1": 9.28,
"zone2": 9.95
}
},
{
"kg": 3,
"estonia": {
"zone1": 4.64,
"zone2": 5.16
},
"latvia": {
"zone1": 10.62,
"zone2": 11.00
}
},
{
"kg": 5,
"estonia": {
"zone1": 5.16,
"zone2": 5.99
},
"latvia": {
"zone1": 12.79,
"zone2": 13.62
}
}
]
See fail sisaldab endast kolme andmekogu: 0.5, 3 ja 5 kg saadetise andmed - need kolm andmekogu on [Listi] sees. Iga sellise {Mapi} sisus on veel eesti ja läti kohta kaks tsooni oma hindadega. Kuidas me nüüd selle Javas kasutatavaks teeme?
public class importJSON {
// Esiteks lae alla Gson.jar ja pane projekti kausta kuskile,
// Soovitatavalt /lib kausta.
// Siis pead projektile ütlema, et lisaks plugina projekti
// ehk Intellij's: File->ProjectStructure->Libraries
// Nüüd saa Gsoni kasutada ja importida
public static void main(String[] args) throws FileNotFoundException,
NoSuchFieldException, IllegalAccessException {
// Avame faili
FileReader reader = new FileReader("dpd.json");
// Impordime faili Javasse
Gson g = new Gson();
KaaluObjekt[] andmed = g.fromJson(reader, KaaluObjekt[].class);
// KaaluObjekt klassi defineerisin allpool
// Testime. Näiteks kui kallis on tsoon 2, läti, 5kg?
double hind = 0;
for (int i = 0; i < andmed.length; i++) {
if (andmed[i].kg == 5) {
hind = andmed[i].latvia.zone2;
}
}
System.out.println(hind);
}
}
// Need kaks klassi määravad ära mis muutujaid salvestada.
// Selle struktuur vastab 1:1 JSONi sisuga.
// ehk KaaluObjekt[] on KaaluObjekt'ide massiiv.
// KaaluObjektil on muutujad kg, estonia, latvia.
// estonia ja latvia on omakorda Tsoon objektid.
// Tsoon objekti sees on kaks muutujat: zone1 ja zone2.
class KaaluObjekt
{
double kg;
Tsoonid estonia;
Tsoonid latvia;
}
class Tsoonid
{
double zone1;
double zone2;
}
Kui sul on nüüd vaja väärtused kätte saada hoopis muutujate kaudu, siis tuleb veidi keerulisemalt kirjutada tsükkel:
for (int i = 0; i < andmed.length; i++) {
if (andmed[i].kg == 5) {
// Võtame Listi seest välja riigi andmed
Object riigiAndmed = andmed[i].getClass().getDeclaredField(riik).get(andmed[i]);
// Võtame riigi andmete seest välja tsoonid
Object tsooniAndmed = riigiAndmed.getClass().getDeclaredField(tsoon).get(riigiAndmed);
// Ja konverteerime "Object" tüüpi muutuja "double" tüübiks
hind = (double) tsooniAndmed;
}
}
Scanneriga saame kasutajalt sisendit. Konsooli põhises programmis on ennekõike klaviatuuri sisestusi vaja kätte saada.
Näite ülesanne
Küsida kasutajalt tema nimi ja vanus.
Scanner sc = new Scanner(System.in);
System.out.println("Mis on sinu nimi?");
String nimi = sc.nextLine();
System.out.println("Mis on sinu vanus?");
int vanus = sc.nextInt();
System.out.printf("Sinu nimi on %s ja vanus %d", nimi, vanus);
Tulemus
Mis on sinu nimi?
Peeter
Mis on sinu vanus?
35
Sinu nimi on Peeter ja vanus 35
Loeb kasutaja sisestust kuni järgmise tühikuni, annab tagasi Stringi.
Loeb kasutaja sisestust kuni rea lõpuni, annab tagasi Stringi.
Võtab kasutajalt täisarvu. Kui kasutaja sisestab täisarvu asemel midagi muud, tuleb error.
Võtab kasutajalt reaalarvu. Kui kasutaja sisestab reaalarvu asemel midagi muud, tuleb error.
Paneb programmi ajutiselt pausile. See on kõige lihtsam viis aega simuleerida, kuid ta ei ole väga täpne ega paindlik. Vt. Timer.
Näiteks
System.out.println("Hommikust!");
Thread.sleep(3000);
System.out.println("Õhtust!");
võtab aega 3 sekundit, sest vahepeal on nii pikk paus.
Timer töötab nagu oleme spordis harjunud. Selle ülesandeks on käivitada mingi toiming mingi kindla aja pärast või siis tsükliliselt käivitada ühte toimingut iga kindla aja tagant.
Timer ei allu enam tavalisele "järjest ülevalt alla" ülesehitusele. Kuna Timeri käivitatav kood läheb käiku vastavalt ajale, siis ta käivitab selleks eraldi Threadi. Kui tuua analoogia programmi ja rongi vahel, siis Timeri käivitudes tekib juurde veel üks rong, mis on esialgse programmi rööbaste kõrval.
Näiteks:
System.out.println("START");
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
System.out.println("TIMER");
}
}, 4000);
System.out.println("Koodi lõpp");
Prindib välja
START
Koodi lõpp
TIMER
Pane tähele, et "Koodi lõpp" jõudis konsooli 4 sekundit varem, kui "TIMER", kuigi koodis on "TIMER" eespool.
Käivita toiming nelja sekundi pärast ühe korra
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
// sinu toimingud
}
}, 4000);
Käivita toiming iga sekund, kuid alusta alles viiendal sekundil
Timer timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
// sinu toimingud
}
}, 5000, 1000);
Vt. .schedule(). Ainuke vahe on see, et fixed rate käivitub ajaliselt väga täpselt. Näiteks kui meil on vaja, et toimingud käivituksid iga 5 sekundi tagant, aga arvuti on jäänud aeglaseks, siis .scheduleAtFixedRate() käivitab koodi kellaajalise täpsusega, .schedule() aga ei arvesta mitte aega vaid millal viimane tsükkel lõppes.
Arrays klass on massiividega manipuleerimiseks. Kuna massiiv (näiteks in[]) on primitiiv, siis tal ei ole enda meetoode. Nagu ArrayListil on täitsa enda .equals() olemas, siis massiivi puhul võtamegi abiks Arrays klassi sama toimingu jaoks.
Sorteeri massiivi väärtused tähestikulises järjekorras.
String[] a = {"ccc", "aaa", "bbb"};
Arrays.sort(a);
Võrdle, kas kaks massiivi on samasugused. Kusjuures, massiivis olevad elemendid peavad olema samas järjekorras, et neid massiive samasugusteks nimetada.
String[] a = {"ccc", "aaa", "bbb"};
String[] b = {"ccc", "aaa", "bbb"};
System.out.println(Arrays.equals(a, b));
Kui massiiv lihtsalt niisama välja printida, tuleb konsooli mingi imelik kood. See kood on pistmist sellega, kuidas arvutis mälu töötab. Meie aga tahame näha massiivi sisu ja seega kasutame .toString() meetodi.
Arrays.toString(a)
Nagu massiividel on Arrays abiks, on ArrayListil, HashMapil ja muudel Collectionitel ka oma abistav klass.
Kuigi ArrayListil on oma .equals() meetod, siis tema .sort() meetod ei tööta päris nii nagu võiks arvata. Collections.sort() aitab meil sorteerida sisalduvad elemendid tähestikulises järjekorras.
Collections.sort(a);
JavaFX on paindlik kasutajaliidese ja graafika kuvaja, samas on ta mõistlikult lihtne kasutada. Kui konsool su vajadusi enam ei rahulda, võta JavaFX ette.
Kindlasti tundub see teema esialgu keeruline, aga kui töötad ühe korra asja läbi leiad, et tegelikult on kõik parajalt lihtne ja loogiline.
Lihtne näide ühest JavaFX programmist on järgmine.
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
public class Valik extends Application{
@Override
public void start(Stage primaryStage) throws Exception {
StackPane stack = new StackPane();
Scene scene = new Scene(stack, 150, 150);
primaryStage.setScene(scene);
Circle ring = new Circle(30);
stack.getChildren().add(ring);
primaryStage.show();
}
}
See programm joonistab lihtsalt ühe ringi.
Esimene asi mis tuleb mõista on, et JavaFX ei ole su programmis enne, kui sa oma põhilist klassi laiendanud (extends
) klassiga Application
.
public class MinuKlass extends Application {
}
Teine tähtis asi on see, et Application klassi laiendades ei alusta sa oma programmi mitte main() meetodiga, vaid start() meetodiga. Muud loogikat siin pole, kui ei Application lihtsalt töötab selliselt.
public class MinuKlass extends Application {
@Override
public void start(Stage primaryStage) {
}
}
@Override
on märge, mis ütleb, et käesolev meetod on super klassist (Application) üle kirjutatud. Nimelt Application klassis on meetod start() juba olemas, aga meie kirjutame selle tegevused enda vajaduse järgi üle.
primaryStage on meie esimene Stage, ehk lava, ehk aken, ehk Window. Võid, kuid ei pea seda kasutama.
Kui JavaFX ülesehitust teatriga võrrelda, siis Stage on lava ja Scene on stseen. Lavakujunduseks on Layout, ehk kuidas esemed paigutuvad stseenis, ja esemed, ehk Node, ise.
Stage on programmi aken. Sisu tuleb ise panna, aga mõned kasulikud meetodid tal siiski on.
Näide
public class MinuKlass extends Application {
@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("MinuÄpp");
primaryStage.show();
}
}
Loo uus
Stage stage = new Stage();
Määra mis Scene on aktiivne.
stage.setScene(scene);
Muuda akna nimi
stage.setTitle("Lahe proge!")
Määra, kas akna suurust saab muuta.
stage.setResizable(boolean);
Too aken nähtavale
stage.show();
Peida aken
stage.hide();
Scene on stseen, ehk nagu tühi konteiner, kus saab action toimuma hakata. Selline vahelüli on vajalik selleks, et saaks ühe käsuga kogu akna sisu ära vahetada. Näiteks kui avaneb programmi aken login vaatesse, siis edukalt sisse logides vahetad login vaate välja programmi vastu.
Loo uus stseen
stack = new StackPane();
Scene scene = new Scene(stack);
Stseeni ilma layoutita teha ei saa, sellepärast on StackPane Scene() sulgude vahel.
Loo uus stseen kindla suurusega
stack = new StackPane();
Scene scene = new Scene(stack, 400, 800);
Muuda tausta värvi hex koodiga.
scene.setFill(Paint.valueOf("#ff0000"));
Layout on lavakujunduses asjade paigutus. Võimalusi on palju. Et kujundused igal ekraanil töötaksid tuleb nad ehitada üles paindlikult, kombineerides erinevaid paneele.
Layout ise ei ole objekt, mida saab luua, Layout kujuneb läbi paneelida.
Täpsemalt saab infot Oracle dokumentatsioonist
Impordi alati javafx paketist! Swing ja AWT on hiljuti aegunud tehnoloogiad.
Kõige lihtsam (ja paindumatum) piksli põhine kujundus. Kõik ülejäänud paneelid pärinevad (extends) siit, st. kõik siinsed meetodid on olemas ka teistel paneelidel.
Loo uus
Pane pane = new Pane();
Lisa sisu hulka element.
pane.getChildren().add(element);
Lisa sisu hulka mitu elementi korraga.
pane.getChildren().addAll(element, element, element);
Positsioneeri sialduvad elemendid alla keskele.
pane.setAlignment(Pos.BOTTOM_CENTER);
Liiguta paneeli allapoole 10 pikslit ja paremale 20 pikslit.
pane.setTranslateY(10);
pane.setTranslateX(20);
Pööra paneeli 30 kraadi.
pane.setRotate(30);
Vähenda mõõtmeid 50%
pane.setScaleX(0.5);
pane.setScaleY(0.5);
Määra eelistatud suuruseks 100x100 pikslit
pane.setPrefSize(100, 100);
Tüüpiline veebikujundus, kus on päis ja jalus, vasak ja parem menüü ning sisu keskel.
Loo uus
BorderPane border = new BorderPane();
Lisa sisu ülemise kasti sisse
border.setTop(sisu);
Lisa sisu alumise kasti sisse
border.setBottom(sisu);
Lisa sisu vasaku kasti sisse
border.setLeft(sisu);
Lisa sisu parema kasti sisse
border.setRight(sisu);
Lisa sisu keskmise kasti sisse
border.setCenter(sisu);
Ka Pane meetodid on siin kasutatavad.
Kui on vaja elemente üksteise peale sobitada. Elemendid satuvad vaikimisi StackPane keskele.
Loo uus
StackPane stack = new StackPane();
Liiguta element üles paremale nurka
stack.setAlignment(element, Pos.TOP_RIGHT);
Liiguta element alla keskele
stack.setAlignment(element, Pos.BOTTOM_CENTER);
Ka Pane meetodid on siin kasutatavad.
Asetab elemendid ruudustiku järgi tabelisse.
Loo uus
GridPane grid = new GridPane();
Lisa element rect ritta 3 veergu 4
grid.add(rect, 4, 3);
Näita ruudustiku jooni
grid.setGridLinesVisible(true);
Ka Pane meetodid on siin kasutatavad.
Paigutab elemendid üksteise alla.
Loo uus
VBox vbox = new VBox();
Lisa 2 pikslit vahet igale elemendile
vbox.setSpacing(2);
Ka Pane meetodid on siin kasutatavad.
Paigutab elemendid vasakult paremale ja ei katke.
Loo uus
Hbox hbox = new Hbox();
Lisa 2 pikslit vahet igale elemendile
hbox.setSpacing(2);
Ka Pane meetodid on siin kasutatavad.
Paigutab elemendid vasakult paremale, katkeb järgmisele reale kui sisu enam ära ei mahu.
Loo uus
FlowPane flow = new FlowPane();
Lisa vaba ruumi horisontaalselt 5 pikslit
flow.setHgap(5);
Lisa vaba ruumi vertikaalselt 5 pikslit
flow.setVgap(5);
Ka Pane meetodid on siin kasutatavad.
Nagu FlowPane, ainult et elemendid saavad kõik identse suuruse.
Loo uus
TilePane tile = new TilePane();
Lisa vaba ruumi horisontaalselt 5 pikslit
tile.setHgap(5);
Lisa vaba ruumi vertikaalselt 5 pikslit
tile.setVgap(5);
Määra eelistatud tulpade arvuks 3
tile.setPrefColumns(2);
Ka Pane meetodid on siin kasutatavad.
Elemente on võimalik ankurdada servadesse ja nurkadesse.
Loo uus
AnchorPane anchor = new AnchorPane();
Ankurda element alla paremasse nurka
anchor.setBottomAnchor(element, 0.0);
anchor.setRightAnchor(element, 0.0);
Kasutajaliides on need nupud ja vidinad, mis teevad su programmi kasutajale interaktiivseks.
Kindlasti impordi ainult javafx pakettidest!!
Järgnevad näited kehtivad kõikidele kasutajaliidese tüüpi elementidele!
Proovime läbi kuidas ühte lihtsat kasutajaliidese tüüp elementi kasutada.
Loo uus
Label l = new Label();
Paneme uue elemendi Layout Pane sisse.
Pane pane = new Pane();
pane.getChildren().add(l);
Vt. ka kuidas JavaFX töötab koos Stage ja Scenega.
Liiguta Label 50 pikslit paremale ja 100 pikslit alla.
l.setTranslateX(50);
l.setTranslateY(100);
Kuigi sa saad muuta elemendi asukohta layouti sees, määrab ümbritsev layout ikkagi olulise osa. Seega, kui su element ei käitu päris nii nagu soovid, proovi mõnda muud layouti.
Vähenda laiust 50% ja kahekordista kõrgus
l.setScaleX(0.5);
l.setScaleY(2);
Pööra 30 kraadi.
l.setRotate(30);
Kõikidest võimalustest räägib täpsemalt Oracle UI Controls, siin on välja toodud esimesed olulised.
Label, ehk silt, on lihtne tekst, mida tüüpiliselt lisatakse mingi interaktiivse elemendi selgitamiseks.
Vt. ka Kasutajaliidese üldine kasutamine.
Määra tekst, ehk Label sisu.
a.setText("Keegi on su selja taga!");
Teksti kirjutamiseks, et kasutajalt infot pärida.
Vt. ka Kasutajaliidese üldine kasutamine.
Lisa välja taustale ajutine tekst
a.setPromptText("Ajutine tekst");
Salvesta kasutaja sisestatud tekst muutujasse
String b = a.getText();
Tühjenda teksti väli
a.clear()
Kui soovid iga muutuse peale reageerida
a.textProperty().addListener((observable, vanaVaartus, uusVaartus) -> {
System.out.println("Uus väärtus: " + uusVaartus);
// Tegevus siia
});
Kui soovid enter
vajutamisele reageerida
a.setOnAction((event) -> {
// Tegevus siia
});
Täpselt nagu TextField, ainult, et kirjutatud tähtede asemel näidatakse tärne.
Vt. ka Kasutajaliidese üldine kasutamine.
Lisa välja taustale ajutine tekst
a.setPromptText("Ajutine tekst");
Salvesta kasutaja sisestatud tekst muutujasse
String b = a.getText();
Tühjenda parooli väli
a.clear()
Kõige lihtsam nupp. Mis juhtub nupu vajutusel saad ise määrata.
Vt. ka Kasutajaliidese üldine kasutamine.
Määra nupu tekst
btn.setText("Vajuta siia!");
Määra mis juhtub kui nuppu vajutatakse
btn.setOnAction((event) -> {
public void handle(ActionEvent e) {
// Siia tegevus, kui nupp on vajutatud.
}
});
Eriline nupp, mis jääb sisse. Kasutatakse selleks, et näiteks mõne programmi settingutes lasta valida jah/ei stiilis või lausa mitme valiku vahel korraga.
Vt. ka Kasutajaliidese üldine kasutamine.
Kui gruppi ei kasuta on üks nupp sisse/välja lülitatav.
ToggleButton nupp = new ToggleButton("üksik toggle");
Toggle nupud grupeeritakse kasutades ToggleGroup objekti. Ühes objektis saab vaid üks nupp olla korraga sisse vajutatud.
ToggleGroup g = new ToggleGroup();
ToggleButton e1 = new ToggleButton("Nupp 1");
ToggleButton e2 = new ToggleButton("Nupp 2");
ToggleButton e3 = new ToggleButton("Nupp 3");
e1.setToggleGroup(g);
e2.setToggleGroup(g);
e3.setToggleGroup(g);
e3.setSelected(true);
vbox.getChildren().addAll(e1, e2, e3);
Radio on veebist vähe tuttavam versioon ToggleButton'ist. Eesmärk on sama: anda kasutajale valida üks mitme seast.
Vt. ka Kasutajaliidese üldine kasutamine.
RadioNupud grupeeritakse ToggleGroup objekti abil, et vaid üks neist saaks olla valitud korraga.
ToggleGroup g = new ToggleGroup();
RadioButton e1 = new RadioButton("Nupp 1");
RadioButton e2 = new RadioButton("Nupp 2");
RadioButton e3 = new RadioButton("Nupp 3");
e1.setToggleGroup(g);
e2.setToggleGroup(g);
e3.setToggleGroup(g);
e3.setSelected(true);
vbox.getChildren().addAll(e1, e2, e3);
RadioButton ja ToggleButton tarbeks.
Küsi ToggleGroup käest, millised nupud on sisse vajutatud
g.getSelectedToggle();
Kasutajale jah/ei stiilis küsimuste esitamiseks.
Vt. ka Kasutajaliidese üldine kasutamine.
Loo 3 CheckBoxi
CheckBox e1 = new CheckBox("Nupp 1");
CheckBox e2 = new CheckBox("Nupp 2");
CheckBox e3 = new CheckBox("Nupp 3");
vbox.getChildren().addAll(e1, e2, e3);
Määra tekstiline sisu.
cd.setText("Nupp 1");
Määra, kas CheckBox on sisse vajutatud.
cb.setSelected(true);
Küsi, kas Checkbox on sisse vajutatud.
cb.isSelected();
Seletav tekst
Vt. ka Kasutajaliidese üldine kasutamine.
Loo ChoiceBox kolme variandiga
ChoiceBox cb = new ChoiceBox(FXCollections.observableArrayList(
"Esimene", "Teine", "Kolmas")
);
pane.getChildren().add(cb);
Küsi milline variant on valitud
cb.getValue();
Reageeri valiku muutmisele.
cb.getSelectionModel()
.selectedItemProperty()
.addListener(
(ObservableValue observable, Object oldValue, Object newValue) -> {
// Do stuff
System.out.println(newValue);
});
Väärtuse valimiseks mingist vahemikust.
Vt. ka Kasutajaliidese üldine kasutamine.
Määra miinimum väärtus
slider.setMin(0);
Määra maksimaalne väärtus
slider.setMax(100);
Määra algne väärtus
slider.setValue(40);
Kas numbrid on näha?
slider.setShowTickLabels(true);
Kas kriipsud on näha?
slider.setShowTickMarks(true);
Kui tihedalt suured kriipsud esinevad.
slider.setMajorTickUnit(50);
Mitu väikest kriipsu on iga suure vahel?
slider.setMinorTickCount(5);
Muuda orientatsioon vertikaalseks.
slider.setOrientation(Orientation.VERTICAL);
Reageeri Slideri muutumise peale
.valueProperty().addListener((observable, vanaVaartus, uusVaartus) -> {
System.out.println("Uus väärtus on: " + uusVaartus.intValue());
});
Kasutab kasutaja operatsioonisüsteemi failihaldurit, et leida kasutaja soovitud fail.
Vt. ka terviklikumat näidet Oracle lehel.
Ava failihaldur ja salvesta fail muutujasse file.
FileChooser fileChooser = new FileChooser();
File file = fileChooser.showOpenDialog(primaryStage);
Määra failihalduri akna pealkiri.
fileChooser.setTitle("Pealkiri");
Vt. Oracle Charts
Joonistada saab joonte, ringide või mistahes muude kujunditega. Polygon näiteks ongi vabalt vormitav kujund.
Soovitatav on konteineriks kasutada Pane layouti, seal ei ole automaatset joondumist ja saab rahulikult x, y koordinaatidega kujundeid moodustada.
On mõned põhitõed, mis kehtivad peaaegu kõikide kujundite puhul:
Loo uus
Rectangle rectangle = new Rectangle(20, 20, 70, 50);
Loo uus eraldi käskudena
Rectangle rec = new Rectangle();
rec.setX(20);
rec.setY(20);
rec.setWidth(70);
rec.setHeight(50);
Reageeri hiire klikile
rectangle.setOnMouseClicked(event -> {
System.out.println("Klikk töötab");
});
Värvi joon või servad.
rectangle.setStroke(Color.RED);
Määra joone paksuseks 10 pikslit.
rectangle.setStrokeWidth(10);
Värvi sisu.
rectangle.setFill(Color.BLUE);
Pööra 45 kraadi.
rec.setRotate(45);
Joonista joon. Määrama peab kust->kuhu kordinaadid, ehk new Line(kustX, kustY, kuhuX, kuhuY).
Vt. ka Joonistamise põhitõed.
Algab koordinaatidelt 0, 0 ja lõppeb 100, 100
Line line = new Line(0, 0, 100, 100);
Sama asi eraldi käskudena
Line line = new Line();
line.setStartX(0);
line.setStartY(0);
line.setEndX(100);
line.setEndY(100);
Ristkülik. Määrata tuleb alguskordinaadid ja laius/kõrgus, ehk new Rectangle(algX, algY, laius, kõrgus).
Vt. ka Joonistamise põhitõed.
Loo uus algusega 20x20 ja suuruses 80x120
Rectangle a = new Rectangle(20,20,80,40);
Sama asi eraldi käskudena
Rectangle a = new Rectangle();
a.setX(20);
a.setY(20);
a.setHeight(80);
a.setWidth(40);
Ring.
Vt. ka Joonistamise põhitõed.
Loo uus
Circle a = new Circle(30);
Muuda raadiust
a.setRadius(30);
Muuda asukohta keskpunkti järgi
a.setCenterX(100);
a.setCenterY(100);
Ellipse on nagu ring, ainult kahe raadiusega - horisontaalne ja vertikaalne.
Vt. ka Joonistamise põhitõed.
Loo uus
Ellipse a = new Ellipse(30, 40);
Muuda raadiust
a.setRadiusX(30);
a.setRadiusY(40);
Muuda asukohta keskpunkti järgi
a.setCenterX(100);
a.setCenterY(100);
Polygon on vaba kujundi joonistaja. Muidu võid ka joonega oma kujundid teha, aga Polygoni saab seest ära värvida.
Vt. ka Joonistamise põhitõed.
Loo uus
Polygon a = new Polygon();
Määra ära otspunktide kordinaadid.
a.getPoints().addAll(new Double[]{
0.0, 0.0,
20.0, 10.0,
10.0, 20.0
});
Antud näites on 3 otspunkti: [(0.0,0.0), (20.0, 10.0), (10.0, 20.0)]
Color klassi abil saad määrata värvi, millega elementi värvida.
Olemasolevaid värve saad valida kirjutades Color.
ja valides paljudest värvidest.
Color.RED;
Color.GREEN;
Color.BLUE;
Color.BLUEVIOLET;
Color.CADETBLUE;
Color.DEEPSKYBLUE;
Kui soovid aga ise värvi koostada RGB formaadis, kasuta selleks Color.rgb()
meetodi.
Color.rgb(255,0,0); // punane
Color.rgb(23,235,78); // Rohekas
Kui oled kinni jäänud, võta siit järjest nõuanded läbi.
Esimene asi mis tee on vajuta ctrl + z
, et oma käike tagasi võtta. Pole mõtet juurde kirjutada koodi kui olemasolev ei tööta. Kui lähed undoga liiale, saad ctrl + shift + z
vajutusega ajaloos edasi minna.
Algajatel juhtub tihti, et Java süntaksit ei järgita. Süntaks on ka programmeerimises grammatika osa. Need on need reeglid, ilma milleta arvuti lihtsalt ei saa aru millest sa räägid. Kontrolli üle järgnevad korduma kippuvad vead:
Kui sulud on korras vajuta ctrl + alt + l
, et treppimine automaatselt korda seada.
Sulul ei ole paarilist
public class MaastikuArhitekt {// klass algab
public void meetod() { // meetod algab
int a = 5;
if (a < 10) { // if algab
a++;
} // if lõppeb
// meetodil POLE lõppu
} // klass lõppeb
Kirjaviga muutujas
public class KosmoseAgentuur {
public static void main(String[] args) {
int aasta = 2030;
if (aasta > 2000) { // aasla => aasta
int millennium = 2;
}
}
}
Sõnel ei ole jutumärke
String auto = Ford Mustang; // õige: "Ford Mustang"
Sõne või tähe ümber on valed jutumärgid
"Sõne on topelt jutumärkidega" != 't'
Mõne rea lõpust on puudu semikoolon
public class KosmoseAgentuur {
public static void main(String[] args) {
int aasta = 2030;
if (aasta < 10) {
System.out.println("Tõene") // puudub ;
}
}
}
Kuskil on liigne semikoolon
public class KosmoseAgentuur {
public static void main(String[] args) {
int aasta = 2030;
if (aasta < 10); { // pärast if ei tohi olla ;
System.out.println("Tõene");
}
}
}
Suur-väike täht valesti (Java on tundlik)
CamelCase != camelCase != Camelcase;
Võrdluses operaatorid sassis
==
on võrdlemiseks ja =
on uue väärtuse omistamiseks.
Tihti annab IDE (Intellij) sulle teada, kus viga on.
Sul tuleb vaid punaseid märguandeid otsida ja hiirega peale minna (mitte vajutada), et lugeda kasulikku vihjet.
Vahel oskab IDE sulle vea isegi ära parandada. Näiteks kui oled unustanud midagi importida siis kliki punasele joonele ja kas alt + enter
vajutades või punasele pirnile klikkides saad kasutada võimalike lahendusi.
Muidugi peaksid ikka umbes teadma mida need lahendused teevad, vahel võib kood hullemaks ka minna.
Kui oma programmi käima paned ja ta punast teksti konsooli viskab, siis otsi sealt tekstist järgnevaid märksõnu. Need on kõige populaarsemad vead, mis võivad tekkida:
ClassNotFoundException
Oled käivitanud vale klassi. Ava õige fail ja vajuta ctrl + shift + f10
. Vt. ka kiirklahve
Class xxxx not found in type declaration
Oled unustanud importida mingi klassi, mida kasutad oma programmis.
ArrayIndexOutOfBounds
Küsid massiivilt positsiooni kohta, mida pole olemas. Pea meeles, et positsioonide loendamine algab nullist. Näiteks massiivis int[] a = {5, 3, 6};
ei ole olemas kohta a[3]
.
Number tuleb vale, näiteks 8.6535634789E120
See E on tähtis, see märgistab, et näitab sulle ligikaudset arvu. "E" on kümne kordaja. Antud näites on arvuks 8.6535634789 * 10 ^ 120.
Kui programm käivitub, aga tulemus ei ole see, mida ootasid.
Eesmärgiks on saada teada täpselt mis tulemuse iga koodirida annab.
Kui enne oli kood:
int a = 5;
if (a < 5) {
a++;
}
Siis nüüd on kõik võimalikud pesad välja prinditud:
int a = 5;
System.out.println("a = " + a);
if (a < 5) {
System.out.println("a = " + a);
a++;
}
System.out.println("a = " + a);
Antud näide on veidi ekstreemne (esimene print on üleliigne) aga vahel tuleb vea leidmiseks olla ekstreemne.
Debug on lahe funktsioon, kus näed rida rea haaval kuidas programm jookseb. Vaata täpsemalt Debuggimine.
Google on meie parim sõber, Googelda nii kuis jaksad. Tihtipeale satud lehele nimega StackOverflow ja see on teine parim abimees.
Foorum on parem kui õppejõult küsimine, sest praktikas saad sealt omale vastuse kiiremini. Ja tänu sinu küsimusele saavad ka teised targemaks.
Viimase variandina küsi õppejõu käes abi. See ei ole sellepärast, et õppejõud ei soovi sulle oma aega pühendada, vaid lihtsalt sellepärast, et vea otsimine on iga progeja igapäevane töö ja ka seda peab iseseisvalt teha oskama. Selge on ka see, et algajale on kõige vaimu tapvam olukord lihtsalt segaduses olemine, seega võta julgelt ühendust, selleks me siin oleme.