Programovanie (1) v C/C++
1-INF-127, ZS 2024/25

Úvod · Pravidlá · Prednášky · Softvér · Testovač
· Kontaktujte nás pomocou e-mailovej adresy E-prg.png (bude odpovedať ten z nás, kto má príslušnú otázku na starosti alebo kto má práve čas).
· Prosíme študentov, aby si pravidelne čítali e-maily na @uniba.sk adrese alebo aby si tieto emaily preposielali na adresu, ktorú pravidelne čítajú.


Letný semester, prednáška č. 5: Rozdiel medzi revíziami

Z Programovanie
Skočit na navigaci Skočit na vyhledávání
Riadok 20: Riadok 20:
 
* Metóda <tt>Iterator<E> iterator()</tt> vráti tzv. ''iterátor'', ktorý možno použiť na postupné prechádzanie cez všetky prvky daného zoskupenia. Ide tu o dôležitý koncept, pri ktorom sa ešte bližšie pristavíme nižšie.
 
* Metóda <tt>Iterator<E> iterator()</tt> vráti tzv. ''iterátor'', ktorý možno použiť na postupné prechádzanie cez všetky prvky daného zoskupenia. Ide tu o dôležitý koncept, pri ktorom sa ešte bližšie pristavíme nižšie.
  
Je ešte potrebné ujasniť si, čo napríklad pri metóde <tt>contains</tt> znamená, že zoskupenie ''obsahuje'' objekt <tt>o</tt>, prípadne kedy sa pri metóde <tt>remove</tt> nejaký objekt považuje za ''výskyt'' jej argumentu. V obdivoch prípadoch sa na porovnávanie objektov používa metóda <tt>equals</tt>, ktorá porovná dva objekty na rovnosť. S touto metódou sme sa už stretli napríklad pri reťazcoch alebo pri &bdquo;baliacich&rdquo; triedach. Ide však o metódu, ktorá je podobne ako <tt>toString</tt> definovaná už v triede <tt>Object</tt> &ndash; jej východzou implementáciou je porovnávanie referencií pomocou operátora <tt>==</tt> &ndash; a v iných triedach môže byť prekrytá prirodzenejšou implementáciou. Programátor tejto implementácie by pritom mal vždy zabezpečiť, aby išlo o reláciu ekvivalencie (reflexívnu, symetrickú a súčasne tranzitívnu reláciu).
+
'''Metóda <tt>equals</tt>.''' Je ešte potrebné ujasniť si, čo napríklad pri metóde <tt>contains</tt> znamená, že zoskupenie ''obsahuje'' objekt <tt>o</tt>, prípadne kedy sa pri metóde <tt>remove</tt> nejaký objekt považuje za ''výskyt'' jej argumentu. V obdivoch prípadoch sa na porovnávanie objektov používa metóda <tt>equals</tt>, ktorá porovná dva objekty na rovnosť. S touto metódou sme sa už stretli napríklad pri reťazcoch alebo pri &bdquo;baliacich&rdquo; triedach. Ide však o metódu, ktorá je podobne ako <tt>toString</tt> definovaná už v triede <tt>Object</tt> &ndash; jej východzou implementáciou je porovnávanie referencií pomocou operátora <tt>==</tt> &ndash; a v iných triedach môže byť prekrytá prirodzenejšou implementáciou. Viacero štandardných tried (napr. <tt>String</tt> a <tt>Integer</tt>) túto metódu vhodným spôsobom prekrýva.
 +
* Programátor prekrytej metódy <tt>equals</tt> by mal vždy zabezpečiť, aby išlo o ''reláciu ekvivalencie'' (reflexívnu, symetrickú a súčasne tranzitívnu reláciu).
 +
* Súčasne by sa výstupy metódy <tt>equals</tt> pre danú dvojicu objektov ''nemali meniť v čase''. To v praxi znamená, že prekrývanie metódy <tt>equals</tt> má význam hlavne pri triedach, ktorých inštancie reprezentujú nemodifikovateľné dáta. Napríklad <tt>String</tt> metódu <tt>equals</tt> zdedenú od triedy <tt>Object</tt> vhodným spôsobom prekrýva, ale <tt>StringBuilder</tt> nie.
 +
* Dátové štruktúry, ktoré sú súčasťou Java Collections, sa na tieto vlastnosti metódy <tt>equals</tt> spoliehajú &ndash; iba za ich splnenia je teda garantované, že sa budú správať očakávaným spôsobom.
  
 
''Príklad'': nasledujúca trieda reprezentuje bod v rovine, pričom dva body sa považujú za rovné kedykoľvek sa rovnajú obidve ich súradnice.
 
''Príklad'': nasledujúca trieda reprezentuje bod v rovine, pričom dva body sa považujú za rovné kedykoľvek sa rovnajú obidve ich súradnice.

Verzia zo dňa a času 16:06, 11. marec 2021

Oznamy

  • Dnes po prednáške bude zverejnené zadanie druhej domácej úlohy, ktorú bude potrebné odovzdať do pondelka 29. marca, 9:00 (čiže do začiatku siedmej prednášky).
  • Na stredajších cvičeniach bude – okrem niekoľkých nebodovaných úloh zameraných na látku z tejto a minulej prednášky – zverejnené aj zadanie druhej bonusovej úlohy s odovzdávaním do stredy 24. marca, 11:30 (čiže najneskôr do začiatku šiestych cvičení).

Java Collections

Detailnejšie teraz preskúmame štandardné dátové štruktúry implementované v balíku java.util a známe pod súhrnným názvom Java Collections. Na nasledujúcom obrázku je znázornený diagram najdôležitejších tried a rozhraní, ktoré sú súčasťou Java Collections. Plná šípka v tomto diagrame reprezentuje dedenie (aj medzi rozhraniami) a prerušovaná čiara reprezentuje rozhranie implementované triedou.

Collections.png

Rozhranie Collection

Veľká časť tried pre dátové štruktúry, ktoré sú súčasťou Java Collections – presnejšie triedy reprezentujúce zoskupenia objektov nejakého typu E – implementuje generické rozhranie Collection<E>. Metódy tohto rozhrania sú tak napríklad poskytované implementáciami zoznamov, či množín. Medzi najdôležitejšie spomedzi metód deklarovaných v rozhraní Collection<E> patria nasledujúce:

  • Metóda boolean contains​(Object o) vráti true práve vtedy, keď dané zoskupenie objektov obsahuje objekt o.
  • Metóda boolean add​(E e) pridá inštanciu e typu E do zoskupenia objektov a vráti booleovskú hodnotu podľa toho, či po vykonaní tejto operácie bolo dané zoskupenie zmenené (napríklad u zoznamov by to tak malo byť vždy; naopak množina sa nezmení v prípade, že je do nej pridaný prvok, ktorý už obsahuje). Pri jednotlivých implementáciách rozhrania Collection<E> môže byť správanie tejto metódy bližšie určené: napríklad u zoznamov sa typicky pridáva na koniec. Táto metóda je označená ako nepovinná, čo znamená, že niektoré implementácie rozhrania Collection<E> ju môžu implementovať iba ako vyhodenie výnimky typu UnsupportedOperationException.
  • Metóda boolean remove​(Object o) odoberie zo zoskupenia jeden výskyt argumentu o. Opäť ide o nepovinnú metódu, ktorej správanie môže byť v jednotlivých implementáciách rozhrania bližšie špecifikované.
  • Metóda int size() vráti veľkosť daného zoskupenia objektov.
  • Metóda boolean isEmpty() zistí, či je dané zoskupenie objektov prázdne.
  • Metóda Iterator<E> iterator() vráti tzv. iterátor, ktorý možno použiť na postupné prechádzanie cez všetky prvky daného zoskupenia. Ide tu o dôležitý koncept, pri ktorom sa ešte bližšie pristavíme nižšie.

Metóda equals. Je ešte potrebné ujasniť si, čo napríklad pri metóde contains znamená, že zoskupenie obsahuje objekt o, prípadne kedy sa pri metóde remove nejaký objekt považuje za výskyt jej argumentu. V obdivoch prípadoch sa na porovnávanie objektov používa metóda equals, ktorá porovná dva objekty na rovnosť. S touto metódou sme sa už stretli napríklad pri reťazcoch alebo pri „baliacich” triedach. Ide však o metódu, ktorá je podobne ako toString definovaná už v triede Object – jej východzou implementáciou je porovnávanie referencií pomocou operátora == – a v iných triedach môže byť prekrytá prirodzenejšou implementáciou. Viacero štandardných tried (napr. String a Integer) túto metódu vhodným spôsobom prekrýva.

  • Programátor prekrytej metódy equals by mal vždy zabezpečiť, aby išlo o reláciu ekvivalencie (reflexívnu, symetrickú a súčasne tranzitívnu reláciu).
  • Súčasne by sa výstupy metódy equals pre danú dvojicu objektov nemali meniť v čase. To v praxi znamená, že prekrývanie metódy equals má význam hlavne pri triedach, ktorých inštancie reprezentujú nemodifikovateľné dáta. Napríklad String metódu equals zdedenú od triedy Object vhodným spôsobom prekrýva, ale StringBuilder nie.
  • Dátové štruktúry, ktoré sú súčasťou Java Collections, sa na tieto vlastnosti metódy equals spoliehajú – iba za ich splnenia je teda garantované, že sa budú správať očakávaným spôsobom.

Príklad: nasledujúca trieda reprezentuje bod v rovine, pričom dva body sa považujú za rovné kedykoľvek sa rovnajú obidve ich súradnice.

public class Point {
    private double x, y;

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    @Override
    public final boolean equals(Object o) {
        if (o instanceof Point) {
            return ((Point) o).x == x && ((Point) o).y == y;
        } else {
            return false;
        }
    }
}
public class Trieda {

    public static void main(String[] args) {
        Point p1 = new Point(1, 2);
        Point p2 = new Point(1, 2);
        System.out.println(p1 == p2);       // false
        System.out.println(p1.equals(p2));  // true
    }
}

Metódu equals sme tu označili ako finálnu, pretože inak by jej prekrytia v prípadných podtriedach triedy Point ľahko porušili požiadavku symetrie (existujú tu ale aj iné prístupy).

Zoznamy

Triedy pre zoznamy sú implementáciami rozhrania List<E>.

  • Prvok na koniec poľa pridáva metóda add, prvok na danej pozícii dostaneme metódou get, metóda set mení prvok na danej pozícii na určenú hodnotu a dĺžku poľa vracia metóda size.

Dvoma najdôležitejšími triedami implementujúcimi rozhranie List<E> sú:

  • Trieda ArrayList<E> reprezentujúca zoznamy implementované pomocou dynamických polí, ktoré dokážu automaticky meniť objem alokovanej pamäte.
Príklad:
import java.util.*;

public class Trieda {

    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<>();
        for (int i = 0; i <= 9; i++) {
            a.add(i);
        }
        for (int i = 0; i <= a.size() - 1; i++) {
            a.set(i, i + 1);
        }
        for (int i = 0; i <= a.size() - 1; i++) {
            System.out.print(a.get(i) + " ");
        }
    }
}
  • Trieda LinkedList<E> reprezentujúca obojsmerne spájaný zoznam.

Každá z týchto dvoch implementácií zoznamov je zameraná na iné operácie, ktoré sú v nej efektívnejšie – z minulého semestra napríklad vieme, že prístup k prvku na konkrétnej pozícii zoznamu je omnoho efektívnejší u polí, zato pri spájaných zoznamoch sa rýchlejšie pridávajú a odoberajú nové prvky (napríklad) na začiatku alebo konci.

Rad a objostranný rad

  • Trieda LinkedList<E> okrem rozhrania List<E> implementuje aj rozhranie Queue<E> reprezentujúce rady (fronty). Na koniec radu pridávame metódou add rovnako ako u zoznamov; metóda remove (bez parametrov) vyberie a vráti na výstupe prvok zo začiatku radu; metóda peek vráti prvok na začiatku radu bez toho, aby ho z radu vybrala.
  • Okrem toho trieda LinkedList<E> implementuje aj rozhranie Deque<E> (z angl. double-ended queue) pre obojstranné rady, v ktorých možno prvky pridávať a vyberať z obidvoch strán. Toto rozhranie okrem iného deklaruje metódy push a pop umožňujúce pracovať s ním ako so zásobníkom.
  • Javovské spájané zoznamy typu LinkedList<E> teda možno použiť aj ako rad, aj ako zásobník.

Množiny

Triedy pre množiny sú implementáciami rozhrania Set<E> a pri práci s nimi sú podstatné predovšetkým metódy add, contains a remove. Najdôležitejšou z nich je trieda HashSet<E>:

  • Ide o implementáciu množín pomocou hešovania.



Iterátory

Zobrazenia

Usporiadané množiny a zobrazenia na nich

Komparátory

Trieda Collections

Vnorené a anonymné triedy

Statické vnorené triedy

Vnorené triedy

Lokálne triedy

Anonymné triedy

Javadoc