Računalništvo 1 (PRA)

lekcije / Razred Vector

Razred Vector

V Javini standrardni knjižnici java.util najdemo imeplementacije raznih podatkovnih struktur. V tej lekciji bomo spoznali vektorje, to je razred Vector.
Kadar v Javi naredimo tabelo z ukazom new, moram povedati, kako velika naj bo tabela. Ko je tabela enkrat narejena, njene velikosti ne moremo spreminjati. To pomeni, da tabeli ne moremo dodajati in odvzemati elementov.
Kadar potrebujemo podatkovno strukturo, ki je kakor tabela, le da želimo dodajati in odvzemati elemente, uporabimo razred Vector.
Osnovne metode za delo z vektorji in primerjavo s tabelami prikazuje naslednja razpredelnica:
Osnovne operacije z vektorji
Vector v = new Vector();Naredi nov vektor (velikosti 0). [tabele: Object[] t = new Object[0];]
Vector v = new Vector(n);naredi vektor/tabelo velikosti n [tabele: Object[] t = new Object[n];]
v.size()velikost vektorja [tabele: t.length]
v.elementAt(k)k-ti element [tabele: t[k]]
v.setElementAt(x, k);nastavi k-ti element na x [tabele: t[k] = x;]
v.firstElement();prvi element [tabele: t[0]]
v.lastElement();zadnji element t[t.length - 1]
v.add(x);dodaj x na konec vektorja [tabele: ne obstaja]
v.insertElementAt(x, k);vrini x na k-to mesto [tabele: ne obstaja]
v.removeElementAt(k);odstrani k-ti element [tabele: ne obstaja]
v.removeAllElements();odstrani vse elemente [tabele: t = new Object[0];]
v.removeRange(i, j);odstrani vse elemente od i-tega do j-tega [tabele: ne obstaja]
v.toArray();pretvori vektor v tabelo
v.toString();predelaj vektor v niz [tabele: ne obstaja]
v.contains(x)ali vektor vsebuje element x? [tabele: ne obstaja]
v.indexOf(x)Indeks, na katerem se pojavi element x [tabele: ne obstaja]
V zgornji tabeli seveda niso naštete vse metode za delo z vektorji. Oglejte si še dokumentacijo! Ker ima razred Vector metodo toString, lahko vektorje izpisujemo z metodo println.
Kadar želimo napraviti kako operacijo za vsak element tabele t, to naredimo s for zanko:
for (int i = 0; i < t.length; i++) {
  tu nekaj naredimo s t[i]
}
Enako lahko naredimo z vektorjem v:
for (int i = 0; i < v.size(); i++) {
  tu nekaj naredimo z v.elementAt(i)
}
Vendar to ni najboljša rešitev, ker prav v ta namen obstaja konstrukt, ki se imenuje iterator. To je objekt, s pomočjo katerega se sprehodimo čez elemente vektorja. Priporočen način je torej takšen:
Iterator it = v.iterator();
while (it.hasNext()) {
  Object x = it.next();
  tu nekaj naredimo z x
}
Metoda hasNext() vrne true, če ima iterator na voljo še kak objekt. Metoda next() vrne naslednji element.
Naloga 1
[rešitev]
Naloga 2
[rešitev]
Naloga 3
[rešitev]
Naloga 4
[rešitev]
Naloga 5
[rešitev]
Naloga 6
[rešitev]
Naloga 7
[rešitev]
Naloga 8
[rešitev]
Naloga 9
[rešitev]
Naloga 10
[rešitev]
Naloga 11
[rešitev]

Rešitve nalog

Naloga 1

Naloga1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.io.*;
import java.util.*;

public class Naloga1 {

  // Vaja 1
  // Napravimo (statieno) metodo, ki kot argument dobi ime vhodne
  // datoteke. Vse vrstice vhodne datoteke prebere v objekt razreda
  // Vector, ki ga vrne kot vrednost. Elementi naj bodo v vektorju v
  // enakem vrstnem redu kot so vrstice na vhodni datoteki.
  public static Vector beri(String ime) throws IOException {
    BufferedReader dat = new BufferedReader(new FileReader(ime));
    Vector vv = new Vector();
    while (dat.ready()) {
      vv.add(dat.readLine());
    }
    dat.close();
    return vv;
  } // beri

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // izpišemo jih na standardni izhod
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga1.beri(args[0]);
    System.out.println(podatki);
  } // main

} // class

Naloga 2

Naloga2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.*;
import java.util.*;

public class Naloga2 {

  // Vaja 2
  // Napravimo (statično) metodo, ki kot argument dobi objekt razreda
  // Vector in ime izhodne datoteke. Vse elemente vektorja izpiše na
  // datoteko po enega v vrstico.
  public static void pisi(Vector vv, String ime) throws IOException {
    PrintWriter dat = new PrintWriter(new FileWriter(ime));
    Iterator it = vv.iterator();
    while (it.hasNext()) {
      String x = (String)it.next();
      dat.println(x);
    }
    dat.close();
  } // pisi

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga1.beri(args[0]);
    pisi(podatki,args[1]);
  } // main

} // class

Naloga 3

Zahtevana metoda je metoda beriS v spodnjem programu.
Komentar v metodi pojasnjuje delovanje.
Naloga3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import java.io.*;
import java.util.*;

public class Naloga3 {

  // Vaja 3
  // Napravimo (statično) metodo, ki kot argument dobi ime vhodne
  // datoteke. Vse vrstice vhodne datoteke prebere v objekt razreda
  // Vector, ki ga vrne kot vrednost. Vsako vrstico iz vhodne
  // datoteke vstavimo v vektor tako, da bodo elementi v vektorju
  // sortirani po abecedi.
  public static Vector beriS(String ime) throws IOException {
  // skelet metode je enak kot pri vaji 1
    BufferedReader dat = new BufferedReader(new FileReader(ime));
    Vector vv = new Vector();
    while (dat.ready()) {
      String ll = dat.readLine();
      // Tu imamo prebrano vrstico ll
      // Odlociti se moramo, kam v Vector vv jo bomo vstavili.
      // Predpostavljamo, da so vsi dosedanji elementi vv že
      // sortirani, kar pomeni, da moramo poiskati tisti kk, kjer
      // je (prvič)  ll <= vv.elementAt(kk).
      // To naredimo tako, da s kk štejemo od 0 do vv.size()-1 in
      // vsakokrat testiramo gornji pogoj; ko najdemo kk, ki ustreza
      // gornjemu pogoju, vstavimo podatek ll v vektor vv in končamo
      // zanko.
      // Posebni (robni) problemi:
      // 1. vektor je prazen: gornji pogoj ne more biti nikoli
      //    izpolnjen, saj ni nobenega elementa - v resnici se zanka
      //    ne bo nikoli izvedla in se bo "naravno" iztekla (brez
      //    break); nov podatek moramo dodati na konec vektorja
      //    (uporabiti vv.add(ll)).
      // 2. podatek je večji od vseh dosedanjih: zanka se bo iztekla,
      //    ker gornji pogoj ni bil nikoli izpolnjen, nov element
      //    moramo dodati na konec vektorja (enako kot v prejšnjem
      //    primeru).
      // 3. Podatek je manjši od vseh v vektorju: Zanka se bo ustavila
      //    v prvi ponovitvi in vse bo enako kot sicer.
      // Gornja primera 1 in 2 torej združimo v enega: če se zanka
      // naravno konča, napravimo vv.add(ll).
      //
      // Zgoraj je primer, kako je smiselno vedno pregledati robne
      // pogoje - izrojene situacije. Skoraj vse programerske napake
      // se pojavljajo v takih izjemnih situacijah.
      //
      // Ker potrebujemo indeks elementa za insertElementAt,
      // uporabljamo kar elementAt in ne Iterator.
      int kk = 0;              // indeks elementa, ki ga pregledujemo
      for (kk = 0; kk < vv.size(); kk++) {
        if (ll.compareTo(vv.elementAt(kk)) <= 0) {
          vv.insertElementAt(ll,kk);  break;     // to je pravo mesto
        }
      }
      if (kk >=vv.size()) {            // zanka se je naravno končala
        vv.add(ll);
      }
    }
    dat.close();
    return vv;
  } // beriS

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = beriS(args[0]);
    Naloga2.pisi(podatki,args[1]);
  } // main

} // class
Opomba: Vector nikakor ni najprimernejša podatkovna struktura za vstavljanje emphelementov. Mi ga uporabljamo zato, ker primernejše (še) ne poznamo in ker smo se odločili, da bomo delali vaje z razredom Vector.
Ne glede na podatkovno strukturo pa pristop sprotnega urejanja podatkov med branjem večinoma nima smisla. Če bi bila celotna naloga le branje in urejen izpis (kot to naredimo v testni metodi main), je pravi pristop branje, sortiranje in izpis. Sprotno urejanje podatkov na načine kot so prikazani v teh rešitvah je prezahtevno v primerjavi z dobrim sortiranjem. Tudi če bi zaradi kakega drugega razloga morali imeti (med branjem) stalno urejene podatke, bi se morali tega lotiti drugače (npr. z urejenim drevesom).

Naloga 4

Naloga4.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.io.*;
import java.util.*;

public class Naloga4 {

  // Vaja 4
  // Napravimo (statično) metodo, ki kot argument dobi objekt razreda
  // Vector in ime izhodne datoteke. Vse elemente vektorja izpiše na
  // datoteko. Elementi iz vektorja naj se izpišejo v abecednem
  // vrstnem redu. Pri tem lahko vsebimo vektorja spremenimo (na
  // koncu je lahko prazen).
  public static void pisiS1(Vector vv, String ime) throws IOException {
    // POZOR: ta metoda je grda, ker spreminja vv!!
    PrintWriter dat = new PrintWriter(new FileWriter(ime));
    while (vv.size() > 0) {
      String min = (String)vv.elementAt(0);       // doslej najmanjši
      int indMin = 0;                    // indeks doslej najmanjšega
      for (int ii = 1; ii < vv.size(); ii++) {
        String x = (String)vv.elementAt(ii);
        if (x.compareTo(min) < 0) {
          min = x; indMin = ii;
        }
      }
      dat.println(vv.remove(indMin));
    }
    dat.close();
  } // pisiS1

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga1.beri(args[0]);
    pisiS1(podatki,args[1]);
  } // main

} // class
Opomba: Vector nikakor ni najprimernejša podatkovna struktura za brisanje elementov. Mi ga uporabljamo zato, ker primernejše (še) ne poznamo in ker smo se odločili, da bomo delali vaje z razredom Vector.
Naša metoda spreminja podatkovno strukturo, ki jo dobi kot parameter. V splošnem to ni pametno obnašanje, ker uporabnik metode na to enostavno pozabi in je zato tako obnašanje pogost vir napak. Nalogo smo zastavili tako le zaradi intuitivne preprostosti postopka. Naslednja naloga to grdo obnašanje odpravi (metoda pisiS).
Vsa sortiranja, ki smo jih napravili v našem programu so le enostavni šolski postopki in niso za resno rabo. Za resno delo moramo uporabiti postopke sortiranja, ki imajo število operacij sorazmerno n * log(n) in ne n2, kot je to v naših primerih (n označuje število elementov tabele).

Naloga 5

Naloga5.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.io.*;
import java.util.*;

public class Naloga5 {

  // Vaja 5
  // Napravimo (statično) metodo, ki kot argument dobi objekt razreda
  // Vector in ime izhodne datoteke. Vse elemente vektorja izpiše na
  // datoteko. Elementi iz vektorja naj se izpišejo v abecednem
  // vrstnem redu. Pri tem mora ostati vsebina vektorja nespremenjena.
  public static void pisiS(Vector vv, String ime) throws IOException {
    boolean[] zbrisan = new boolean[vv.size()];  // označuje zbrisane
    PrintWriter dat = new PrintWriter(new FileWriter(ime));
    int indMin;         // indeks doslej najmanjšega; -1, če ga še ni
    do { // računamo na to, da je tabela zbrisan nastavljena na false
      String min = "";                            // doslej najmanjši
      indMin = -1;
      for (int ii = 0; ii < vv.size(); ii++) {
        if (!zbrisan[ii]) {                    // zbrisane preskočimo
          String x = (String)vv.elementAt(ii);
          if (indMin < 0 | x.compareTo(min) < 0) {
            min = x; indMin = ii;     // manjši od doslej najmanjšega
          }
        }
      }
      if (indMin >= 0) {    // imamo minumum (sicer je vektor prazen)
        dat.println(vv.elementAt(indMin));
        zbrisan[indMin] = true;
      }
    } while (indMin >= 0);
    dat.close();
  } // pisiS


  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga1.beri(args[0]);
    pisiS(podatki,args[1]);
  } // main

} // class

Naloga 6

Zahtevana metoda je metoda sort v spodnjem programu.
Alternativna in malce boljša je metoda bubbleSort.
Komentarji v programu pojasnjujejo delovanje.
Naloga6a.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import java.io.*;
import java.util.*;

public class Naloga6a {

  // Vaja 6
  // Napravimo (statično) metodo, ki kot argument dobi objekt razreda
  // Vector in vrne isti objekt, le da so elementi v njem sortirani po
  // velikosti.
  public static Vector sort(Vector vv) {
    // Tole je primitiven postopek za urejanje (selection sort)
    // ni za resno rabo, ker se izvaja s kvadratno kompleksnostjo
    // tudi med kvadratnimi urejanji je ta postopek slab, ker teče
    // kvadratno tudi na urejenih tabelah (bubble sort - mehurčno
    // urejanje je prav tako enostavno, ampak boljše in celo uporabno
    // za majhne tabele.
    int ss = vv.size();
    // sortiran del tabele bo rastel od začetka; s vsako ponovitvijo
    // spodnje zanke bomo pridelali en element na pravem mestu
    // spremenljivka zeSortiran kaže (na koncu zanke) na zadnji že
    // sortiran element
    for (int zeSortiran = 0; zeSortiran < ss-1; zeSortiran++) {
      // poiščemo najmanjši element nesortiranega dela tabele
      String min = (String)(vv.elementAt(zeSortiran));
      int indMin = zeSortiran;
      for (int ii = indMin+1; ii < ss; ii++) {
        if (min.compareTo(vv.elementAt(ii)) > 0) {
          min = (String)(vv.elementAt(ii)); indMin = ii;
        }
      }
      // zamenjamo prvega nesortiranega in najmanšega
      Object tt = vv.elementAt(zeSortiran);
      vv.setElementAt(vv.elementAt(indMin),zeSortiran);
      vv.setElementAt(tt,indMin);
    }
    return vv;
  } // sort

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga1.beri(args[0]);
    sort(podatki);
    Naloga2.pisi(podatki,args[1]);
  } // main

} // class
Naloga6b.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import java.io.*;
import java.util.*;

public class Naloga6b {

  // Vaja 6
  // Napravimo (statično) metodo, ki kot argument dobi objekt razreda
  // Vector in vrne isti objekt, le da so elementi v njem sortirani po
  // velikosti.
  // DRUGA VERZIJA
  public static Vector bubbleSort(Vector vv) {
    // Tole je primitiven postopek za urejanje (bubble sort - mehurčno
    // urejanje). Uporaben je za majhne tabele. Kompleksnost še vedno
    // raste s kvadratom dolžine tabele.
    int ss = vv.size();
    // Ideja je naslednja (zaradi analogije s prejšnjim postopkom,
    // bomo tudi ta postopek napisali tako, da že sortiran del na
    // začetku, čeprav se ga tradicionalno napiše tako, da sortiran
    // del tabele nastaja na koncu tabele):
    //
    // Prav tako kot prej, imamo tabelo razdeljeno na že sortiran
    // in še nesortiran del.
    // Prav tako bomo poiskali najmanjši element nesortiranega dela
    // in ga dali na začetek, le da bomo to storili malce drugače.
    // Od konca nesortiranega dela tabele bomo šli na začetek in
    // vsakokrat primerjali dva sosednaj elementa. Če sta v napačnem
    // vrstnem redu (večji pred manjšim), ju zamenjamo. Ker se
    // najmanjši element nesortiranega dela vedno zamenja s sosedi,
    // bo zagotovo prišel na vrh. Spotoma pa bomo nekaj reda napravili
    // tudi med ostalimi pari.
    // Ko smo prišli z najmanjšim elementom do vrha nesortiranega
    // dela tabele, vemo, da so vsi elementi nad zadnjo menjavo
    // zagotovo že sortirani, zato si lahko ustrezno označimo konec
    // sortiranega dela rabele.
    int zeSortiran = 0;        // ni nobenega že sortiranega elementa
    while (zeSortiran < ss) {
      int zadnjaMenjava = zeSortiran;
      // poiščemo najmanjši element nesortiranega dela tabele
      for (int ii = ss-2; ii >= zeSortiran ; ii--) {
        if (((String)(vv.elementAt(ii))).compareTo(vv.elementAt(ii+1)) > 0) {
          Object tt = vv.elementAt(ii);
          vv.setElementAt(vv.elementAt(ii+1),ii);
          vv.setElementAt(tt,ii+1);
          zadnjaMenjava = ii;
        }
      }
      zeSortiran = zadnjaMenjava+1;
    }
    return vv;
  } // bubbleSort

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga1.beri(args[0]);
    bubbleSort(podatki);
  //  Collections.sort(podatki);
    Naloga2.pisi(podatki,args[1]);
  } // main

} // class
Opomba: Vsa sortiranja, ki smo jih napravili v okviru teh vaj so le enostavni šolski postopki in niso za resno rabo. Za resno delo moramo uporabiti postopke sortiranja, ki imajo število operacij sorazmerno n *log(n) in ne n2, kot je to v naših primerih (n označuje število elementov tabele).
Dobra metoda za sortiranje je npr. sort v razredu java.util.Arrays in posebna varianta Collections.sort v razredu java.util.Collections. Namesto klica naše metode sort(vektor) bi uporabili
Collections.sort(vektor);
kot je zapisano v komentarju v main.

Naloga 7

Razred Student definiramo takole:
Student.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Osnovni podatki o studentu: ime, priimek, ocena

public class Student implements Comparable {

  // komponente
  String ime;
  String priimek;
  int ocena;

  // konstruira Studenta iz komponent
  public Student(String ii, String pp, int oo) {
    ime = ii;
    priimek = pp;
    ocena = oo;
  } // Student

  // konstruira Studenta iz niza, kjer so s TAB ločeni
  // ime, priimek, ocena (v tem vrstnem redu)
  public Student(String ss) {
    String[] tt = ss.split("\\s"); // če bi hoteli imeti za delimiter
    // le TAB, bi napisali \t; \\s ujame vse vrste presledkov
    ime = tt.length > 0 ? tt[0] : "";
    priimek = tt.length > 1 ? tt[1] : "";
    try { ocena = Integer.parseInt(tt[2]); }
    catch (Exception ee) { ocena = 0; }
  } // Student

  // podatke o Studentu vrnemo kot niz
  public String toString() {
    return ime + " " + priimek + " " + ocena;
  } // toString

  // običajna metoda compareTo,
  // primerja priimek in nato ime (če sta priimka enaka)
  public int compareTo(Object s2) {
    int rv = 0;
    Student ss = (Student)s2;
    if ((rv = this.priimek.compareTo(ss.priimek)) != 0) return rv;
    return this.ime.compareTo(ss.ime);
  } // compareTo

  // običajna metoda equals, primerja priimek in ime
  public boolean equals(Object s2) {
    return this.compareTo((Student)s2) == 0;
  } // equals

} // class
Edina drobna komplikacija je v konstruktorju, ki konstruira nov objekt iz niza. Uporablja metodo split(), ki smo jo že večkrat srečali. Za vsako komponento posebej preveri, ali je bila navedena v vhodni vrstici, da bo program deloval tudi ob manjkajočih podatkih. Posebej se potrudimo, da manjkajoča ali napačna ocena pomeni oceno 0.
V razredu smo pravilno deklarirali metodi equals in compareTo zaradi zadnje smo lahko navedli, da implementiramo vmesnik Comparable. To nam bo omogočilo uporabo splošnih metod za iskanje in sortiranje v vektorju.
Programček iz naloge 1 lahko popravimo takole:
Naloga7.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.*;
import java.util.*;

public class Naloga7 {

  // Vaja 7
  // Napravimo podobno metodo kot v prvi nalogi, le da vemo, da so na
  // datoteki podatki sestavljeni iz imena in priimka študenta ter
  // ocene. Podatki na vhodni datoteki so med seboj ločeni z znaki
  // TAB. Definirajmo razred Student, ki bo vseboval vse tri
  // komponente. V razredu Student definirajmo tudi metodi toString
  // in compareTo (študente med seboj primerja po abecedi). Statična
  // metoda naj vrne vektor objektov razreda Student.

  // Razred Student je definiran na ločeni datoteki

  public static Vector beriStudent(String ime) throws IOException {
    BufferedReader dat = new BufferedReader(new FileReader(ime));
    Vector vv = new Vector();
    while (dat.ready()) {
      {{vv.add(new Student(dat.readLine()));}}
    }
    dat.close();
    return vv;
  } // beriStudent

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // izpišemo jih na standardni izhod
  public static void main(String[] args) throws IOException {
    Vector podatki = beriStudent(args[0]);
    System.out.println(podatki);
  } // main

} // class
Edina spremenjena vrstica je označena.
V programu smo namesto split("\t") zapisali kar split("\\s"), kar pomeni, da so ločila med podatki v vrsti lahko kakršnikoli presledki ("beli znaki", "whitespace"). Ker v posameznih podatkih (ime, priimek, ocena) ne pričakujemo presledkov, je to povsem smiselno.
Testna datoteka ja npr. taka
Studenti1.dat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Alenka	Žeks	5
Aljoša	Balažek	1
Amir	Cesar	8
Anže	Deršek	2
Ana-Marija	Đurić	5
Barbara	Germovšek	4
Branka	Hren	3
Damijana	Javornik	8
Damjana	Jerman	7
Gorazd	Karba	4
Ivana	Kirm	3
Katja	Kožar	2
Maja	Kojzek	5
Maja	Komić	8
Marjana	Leban	5
Matej	Lesar	4
Melinda	Levičar	6
Miran	Medvešček	8
Natalija	Mušič	4
Nina	Pavlin	5
Nina	Podbregar	9
Peter	Sedej	2
Primož	Skok	6
Renata	Skok	1
Romana	Strauss	6
Sebastjan	Tomažič	6
Tadeja	Valner	9
Opozorilo: datoteka vsebuje znake TAB, ki jih TextPad - če je tako nastavljen - z veseljem spremeni v presledke.
Delovanje programa na gornjih testnih podatkih je tako:
> java Naloga7 Studenti1.dat
[Alenka Žeks 5, Aljoša Balažek 1, Amir Cesar 8, Anže Deršek 2, Ana-Ma
rija Đurić 5, Barbara Germovšek 4, Branka Hren 3, Damijana Javornik 8
, Damjana Jerman 7, Gorazd Karba 4, Ivana Kirm 3, Katja Kožar 2, Maja
 Kojzek 5, Maja Komić 8, Marjana Leban 5, Matej Lesar 4, Melinda Levi
čar 6, Miran Medvešček 8, Natalija Mušič 4, Nina Pavlin 5, Nina Podbr
egar 9, Peter Sedej 2, Primož Skok 6, Renata Skok 1, Romana Strauss 6
, Sebastjan Tomažič 6, Tadeja Valner 9]

Naloga 8

Rešitev, ki uporablja metodo toString v razredu Student, je tule.
Naloga8.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.io.*;
import java.util.*;

public class Naloga8 {

  // Vaja 8
  // Enaka nakoga kot naloga 2, le da so v vektorju objekti razreda
  // Student.
  public static void pisiStudent(Vector vv, String ime)
      throws IOException {
    PrintWriter dat = new PrintWriter(new FileWriter(ime));
    Iterator it = vv.iterator();
    while (it.hasNext()) {
	{{Student x = (Student)it.next();}}
      dat.println(x);
    }
    dat.close();
  } // pisi

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    {{Vector podatki = Naloga7.beriStudent(args[0]);}}
    {{pisiStudent(podatki,args[1]);}}
  } // main

} // class
Metoda pisiStudent je skoraj enaka metodi pisi v nalogi 2. V resnici bi lahko v obeh primerih deklarirali spremenljivko x namesto tipa String ali Student kar s tipom Object in v tem primeru bi bili obe metodi povsem enaki.

Naloga 9

Naloga9.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.io.*;
import java.util.*;

public class Naloga9 {

  // Vaja 9
  // Enaka naloga kot naloga 3, le da so v vektorju objekti razreda
  // Student.
  public static Vector beriStudentS(String ime) throws IOException {
    BufferedReader dat = new BufferedReader(new FileReader(ime));
    Vector vv = new Vector();
    while (dat.ready()) {
      Student ll = new Student(dat.readLine()); /*M*/
      int kk = 0;              // indeks elementa, ki ga pregledujemo
      for (kk = 0; kk < vv.size(); kk++) {
        if (ll.compareTo((Student)vv.elementAt(kk)) <= 0) { /*M*/
          vv.insertElementAt(ll,kk);  break;     // to je pravo mesto
        }
      }
      if (kk >=vv.size()) {            // zanka se je naravno končala
        vv.add(ll);
      }
    }
    dat.close();
    return vv;
  } // beriStudentS

  // testni glavni program
  // podatke preberemo iz datoteke, ki jo navedemo kot prvi argument
  // in jih zapisemo na datoteko, ki jo navedemo kot drugi argument
  public static void main(String[] args) throws IOException {
    Vector podatki = beriStudentS(args[0]); /*M*/
    Naloga8.pisiStudent(podatki,args[1]); /*M*/
  } // main

} // class

Naloga 10

Z upoštevanjem nasvetov v namigu k tej nalogi definiramo razred StudentR1 takole
StudentR1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Dodatni podatki o studentu: ime, priimek, ocena

public class StudentR1 extends Student {

  // komponente
  int ocena2;

  // konstruira StudentaR1 iz komponent
  public StudentR1(String ii, String pp, int oo, int o2) {
    super(ii,pp,oo);
    ocena2 = o2;
  } // StudentR1

  // konstruira StudentaR1 iz niza, kjer so s TAB ločeni
  // ime, priimek, ocena (v tem vrstnem redu)
  public StudentR1(String ss) {
    super(ss);
    ocena2 = 0;
  } // StudentR1

  // podatke o StudentuR1 vrnemo kot niz
  public String toString() {
    return ime + " " + priimek + " " + ocena + " " + ocena2;
  } // toString

  // Spodnji dve metodi uporabljamo zato, ker vedno beremo le
  // komponento ocena. Prvo verzijo uporabimo, ko smo našli študenta,
  // ki je že v tabeli. Drugo verzijo uporabimo, ko imamo študenta,
  // ki ga še ni v tabeli.

  // oceno prepiše iz student.ocena v this.ocena2
  public void nastavi2(StudentR1 student) {
    this.ocena2 = student.ocena;
  } // nastavi2

  // oceno prepiše iz this.ocena v this.ocena2
  public void nastavi2() {
    this.ocena2 = this.ocena;
    this.ocena = 0;
  } // nastavi2

} // class
Obe verziji metod nastavi2 sta pripravljeni zato, da bomo lahko prepisali komponento ocena v ocena2.
Spodnja metoda beriDva prebere dve enako formatirani datoteki in vse podatke vrne v vektorju.
Naloga10.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import java.io.*;
import java.util.*;

public class Naloga10 {

  // Vaja 10
  // Na osnovi razreda Student napravimo razred StudentR1, ki bo
  // vseboval vse komponente Studenta, poleg tega pa še oceno na
  // drugem kolokviju. Napišimo statično metodo, ki bo dobila imeni
  // dveh datotek (prve z rezultati prvega kolokvija in druge z
  // rezultati drugega kolokvija).
  // Metoda bo prebrala obe datoteki in vrnila vektor objektov
  // razreda StudentR1. V vektorju se lahko vsak student pojavi le
  // enkrat. Upoštevajmo, da se lahko posamezni študent pojavi le v
  // eni datoteki, tedaj naj ima oceno iz drugega kolokvija enako 0.
  public static Vector beriDve(String ime1, String ime2)
      throws IOException {
    // prvo datoteko beremo po starem (kot v nalogi 7)
    // metode Naloga7.beriStudent() ne moremo direktno uporabljati,
    // ker dela objekte razreda Student in ne StudentR1
    BufferedReader dat = new BufferedReader(new FileReader(ime1));
    Vector vv = new Vector();
    while (dat.ready()) {
      vv.add(new StudentR1(dat.readLine())); /*M*/
    }
    dat.close();
    // preberemo še drugo datoteko
    dat = new BufferedReader(new FileReader(ime2));
    while (dat.ready()) {
      // študenta preberemo kar v nov objekt (zato, da konstruktor
      // opravi vse delo)
      StudentR1 ss = new StudentR1(dat.readLine()); /*M*/
      int ind = vv.indexOf(ss);// indeks ss v vektorju (-1, če ga ni)
      if (ind < 0) {                                   // nov študent
        ss.nastavi2();  vv.add(ss);
      }
      else {                                      // obstoječ študent
        ((StudentR1)vv.elementAt(ind)).nastavi2(ss);
      }
    }
    dat.close();
    return vv;
  } // beriDve

  // testni glavni program
  // podatke preberemo iz datotek, ki jo navedemo kot prvi in drugi argument
  // izpi1emo jih na standardni izhod
  public static void main(String[] args) throws IOException {
    Vector podatki = beriDve(args[0], args[1]);
    System.out.println(podatki);
  } // main

} // class

Naloga 11

Naloga11.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import java.io.*;
import java.util.*;

public class Naloga11 {

  // Vaja 11
  // Metodo iz naloge 8 popravimo na razred StudentR1. Izpiše naj eno
  // datoteko z obema ocenama pri vsakem študentu.
  public static void pisiVse(Vector vv, String ime)
      throws IOException {
    PrintWriter dat = new PrintWriter(new FileWriter(ime));
    Iterator it = vv.iterator();
    while (it.hasNext()) {
      StudentR1 x = (StudentR1)it.next(); /*M*/
      dat.println(x);
    }
    dat.close();
  } // pisiVse

  // testni glavni program
  // podatke preberemo iz datotek, ki jo navedemo kot prvi in drugi argument
  // izpišemo jih na datoteko navedeno kot tretji argument
  public static void main(String[] args) throws IOException {
    Vector podatki = Naloga10.beriDve(args[0], args[1]);  /*M*/
    Collections.sort(podatki); // dodatno sortiranje (ni zahtevano) /*M*/
    pisiVse(podatki,args[2]);  /*M*/
  } // main

} // class