Návrhový vzor Iterátor (Iterator) slouží k vytvoření rozhraní, které umožňuje sekvenčně procházet objekty uložené v nějaké složité struktuře (kontejneru). Samotná implementace tohoto rozhraní zůstává uživateli skryta. Iterátor patří mezi tzv GoF (Gang of Four) vzory – je součástí bible návrhových vzorů – knihy Design Patterns: Elements of Reusable Object-Oriented Software.

Motivace

Iterátor použijeme v několika částečně se překrývajících situacích.

Průchod složitého objektu

První z nich je, chceme-li procházet objekt, jehož struktura není na první pohled zřejmá. Příkladem může být třída Rodina, ve které existuje velké množství vazeb (rodič, potomek, švagr, teta, sestřenice...). Rozhraní iterátoru nám zaručí, že projdeme systematicky všechny členy rodiny (žádného nevynecháme, ani nezpracujeme vícekrát).

Jednotné rozhraní

Druhou situací je, když chceme vytvořit jednotné rozhraní pro mnoho různých kolekcí. Toto rozhraní pak implementujeme například pro spojový seznam, strom, dynamické pole a podobně. V programu má pak uživatel možnost procházet všechny kolekce jednotným způsobem, aniž by se musel zajímat o to, jak jsou data uložená.

Optimalizace průchodu

Třetím uplatněním iterátoru je optimalizace průchodu kolekcí. Uvažme spojový seznam, který pro přístup používá pouze běžně implementovanou metodu get (pokud chceme n-tý prvek, tak musíme přeiterovat vždy n-1 předchozích uzlů). Pokud bychom chtěli projít postupně všechny prvky, tak potřebujeme 1+2+3 + \\cdots + n = (n+n^{2})/2 = O(n^{2}) operací. V případě použití iterátoru, který by si držel stav (pozici ve spojovém seznamu) a vždy pouze přešel o uzel dál, by počet operací klesl na O(n).


Příklad

Implementujte iterátor pro jednosměrně zřetězený spojový seznam. Iterátor bude obsahovat metody hasNext – dotaz na existenci dalšího prvku – a next – přechod na další prvek (uzel). Navrácený iterátor bude pro usnadnění průchodu kolekcí vždy inicializován na pozici -1 (tj. před první prvek).

001./**
002. * Jednosmerne zretezeny spojovy seznam
003. * @author Pavel Micka
004. * @param <ENTITY> typovy parametr specifikujici ukladany typ
005. */
006.public class MyLinkedList<ENTITY>{
007. 
008.    private Node first;
009.    private Node last;
010.    private int size;
011. 
012.    /**
013.     * Konstruktor spojoveho seznamu
014.     */
015.    public MyLinkedList() {
016.        this.size = 0;
017.    }
018. 
019.    /**
020.     * Vlozi na konec seznamu prvek
021.     * @param i prvek k vlozeni
022.     */
023.    public void add(ENTITY i) {
024.        Node n = new Node(i);
025.        if (size == 0) {
026.            this.first = n;
027.            this.last = n;
028.        } else {
029.            this.last.next = n;
030.            this.last = n;
031.        }
032.        size++;
033.    }
034. 
035.    /**
036.     * Vrati prvek na indexu i
037.     * @param i index prvku
038.     * @throws IndexOutOfBoundsException pokud je i vyssi nebo rovna delce seznamu
039.     * @throws IllegalArgumentException pokud je i zaporne
040.     * @return prvek na indexu i
041.     */
042.    public ENTITY get(int i) {
043.        if (i >= size) {
044.            throw new IndexOutOfBoundsException("Mimo meze index:" + i + ", size:" + this.size);
045.        }
046.        if (i < 0) {
047.            throw new IllegalArgumentException("Index mensi nez 0");
048.        }
049.        Node curr = first;
050.        for (int j = 0; j < i; j++) {
051.            curr = curr.next;
052.        }
053.        return curr.value;
054.    }
055. 
056.    /**
057.     * Smaze prvek na indexu i
058.     * @param i index mazaneho prvku
059.     * @throws IndexOutOfBoundsException pokud je i vyssi nebo rovna delce seznamu
060.     * @throws IllegalArgumentException pokud je i zaporne
061.     */
062.    public void remove(int i) {
063.        if (i >= size) {
064.            throw new IndexOutOfBoundsException("Mimo meze index:" + i + ", size:" + this.size);
065.        }
066.        if (i < 0) {
067.            throw new IllegalArgumentException("Index mensi nez 0");
068.        }
069.        if (i == 0) {
070.            first = first.next;
071.        } else {
072.            Node curr = first;
073.            for (int j = 0; j < i - 1; j++) { //najdeme predchozi
074.                curr = curr.next;
075.            }
076.            curr.next = curr.next.next; //a mazany prvek vynechame
077.            if (i == size - 1) { //pokud mazeme posledni
078.                last = curr;
079.            }
080.        }
081.        size--;
082.    }
083. 
084.    /**
085.     * Dotaz na delku seznamu
086.     * @return delka seznamu
087.     */
088.    public int size() {
089.        return this.size;
090.    }
091. 
092.    /**
093.     * Klasicka toString metoda, vraci textovou reprezentaci objektu
094.     * @return textova reprezentace objektu
095.     */
096.    @Override
097.    public String toString() {
098.        StringBuilder builder = new StringBuilder();
099.        Node curr = first;
100.        for (int i = 0; i < this.size; i++) {
101.            builder.append(curr.value);
102.            builder.append(" ");
103.            curr = curr.next;
104.        }
105.        return builder.toString();
106.    }
107. 
108.    public Iterator<ENTITY> iterator() {
109.        return new LinkedListIterator();
110.    }
111.     
112.    /**
113.     * Vnitrni trida reprezentujici jeden uzel spojoveho seznamu
114.     */
115.    private class Node {
116. 
117.        private ENTITY value;
118.        private Node next;
119. 
120.        private Node(ENTITY value) {
121.            this.value = value;
122.        }
123.    }   
124.     
125.    /* *************************************************
126.     *                   ITERATOR                      * 
127.     * *************************************************/
128.      
129.    /**
130.     * Jednoduchy iterator pro spojovy seznam
131.     * Neresi situaci, kdy je iteratoru pod rukou pozmena kolekce (tj. neni fail fast)
132.     * @param <ENTITY> typovy parametr specifikujici typ ulozeny v prochazene kolekce
133.     *
134.     * Poznamka: Jelikoz je iterator vytvaren jako soukroma vnitrni trida, tak
135.     * je dokanale skryt (zapouzdren) pred okolnim svetem. Veskera jeho volani
136.     * mohou byt uskutecnena pouze skrze inteface iterator
137.     *
138.     * Poznamka2: V realnem Java svete bychom pouzili pro iterator interface
139.     * java.util.Iterator a pro iterovanou tridu interface java.lang.Iterable.
140.     * Tato implementace slouzi pouze jako ukazka vzoru samotneho bez navaznosti
141.     * na tato Java-specific rozhrani
142.     */
143.    private class LinkedListIterator implements Iterator<ENTITY>{
144.        /**
145.         * Odkaz na soucasny uzel spojoveho seznamu
146.         */
147.        private Node currNode;
148.        /**
149.         * Priznak toho, ze je iterator nastaven na -1 prvek
150.         * (tj. jeste nebyl pouzit k prechodu na prvni prvek)
151.         */
152.        private boolean start;
153. 
154.        public LinkedListIterator() {
155.            this.currNode = null;
156.            this.start = true;
157.        }
158. 
159.        @Override
160.        public boolean hasNext() {
161.            if (start) {
162.                return first != null;
163.            }
164.            return currNode.next != null;
165.        }
166. 
167.        @Override
168.        public ENTITY next() {
169.            if (start) {
170.                start = false;
171.                currNode = first;
172.            } else {
173.                currNode = currNode.next;
174.            }
175.            return currNode.value;
176.        }
177.    }
178.}
179. 
180./**
181. * Rozhrani iteratoru. Iterator slouzi k sekvencnimu pruchodu pres objekty ulozene v kolekci/kontejneru
182. * @author Pavel Micka
183. * @param <ENTITY> typovy parametr iteratoru
184. */
185.interface Iterator<ENTITY>{
186.    /**
187.     * Dotaz na existenci dalsiho prvku
188.     * @return @true, pokud dalsi prvek existuje, @false v opacnem pripade
189.     */
190.    public boolean hasNext();
191.    /**
192.     * Navrati dalsi entitu
193.     * @return dalsi entita ("dalsi" je zavisle na konkretni implementaci iteratoru)
194.     */
195.    public ENTITY next();
196.}

SEO od společnosti Digital Pylon


Online casino s algoritmem

České casino online online slot-vegas.cz

Hrajte nejlepší hry jako je GoodGame Empire.





Zajímavé články: Jak najít práci snů? Zvolte kariéru v IT!, Češi mají rádi hrací automaty online, Jak funguje algoritmické obchodování Casino, Online výuka Algoritmus a online marketing mají svá pravidla, Automaty, Matematický vliv, Ratings, Jak fungují algoritmy hazardních her online: více znalostí, více peněz, SYPWAI - nástroj pro vědecký vývoj, Vynikají na globálním trhu: Nejlepší vývojáři softwaru pro online výherní automaty, Jak si vybrat nejlepší české online casino, Proč byste měli hrát online casino VPN revoluce, Kde najdeme algoritmy v každodenním životě?, Čeká vás pracovní pohovor mimo město? Podívejte se, jak dokonale zvládnout včasný příchod, 5 úžasných technologií ze světa hazardních her, Mirror and access to Mostbet, Svou kancelář můžete mít stále po ruce, Jaké výhody má digitalizovaná firma oproti off-line konkurenci?, Jaký systém vybrat pro snadné řízení výroby?, Nahradí umělá inteligence ajťáky?, Důvody, proč používat SnapTik ke stahování videí TikTok, Dokonalý den na pláži: Co si vzít s sebou, aby byl výlet zábavný a bezpečný?, Jak přežít dlouhý let?, Go pay GoodGame Empire, Blockchain, Rozhovor, Umělá inteligence, Ochranná známka pre softvér: Prečo ju registrovať?, Role kryptografických algoritmů v zabezpečení online kasin, Jaké jsou náklady na nákup 3D tiskárny?, Jak algoritmy vylepšují online zážitky v roce 2025, Epilace laserem a péče o pokožku před a po ní, Byty k pronájmu Sokolov - výhody a rizika pronájmu bytu bez realitky, Filmy a seriály plné hádanek: kryptografie jako hlavní téma