JavaRush /Java Blogu /Random-AZ /İterator nümunəsi

İterator nümunəsi

Qrupda dərc edilmişdir
Bu gün Java-da İteratorun nə olduğunu və nə üçün lazım olduğunu danışacağıq .
İterator nümunəsi - 1
Yəqin ki, artıq bildiyiniz kimi, Java-nın İterator interfeysini həyata keçirən gözəl Kolleksiya interfeysi var. İcazə verin, dərhal rezervasiya edim: iterator interfeysi Java-dakı iterator nümunəsi ilə qarışdırılmamalıdır! Aydınlaşdırmaq üçün əvvəlcə interfeysə baxaq.
Hərfi mənada, "İterator" "kobud qüvvə " kimi tərcümə edilə bilər . Yəni, kolleksiyadakı bütün elementləri təkrarlaya bilən müəyyən bir varlıqdır. Üstəlik, bu, daxili quruluşa və kolleksiyaların təşkilinə diqqət yetirmədən bunu etməyə imkan verir.
Bir anlığa təsəvvür edək ki, Java-da iterator yoxdur. Bu halda, hər biri kolleksiyaların ən dərinliklərinə girməli və ondan nəyin fərqli olduğunu həqiqətən dərk etməli ArrayListolacaq . LinkedListHashSetTreeSet

İteratorun həyata keçirməli olduğu üsullar

boolean hasNext()— təkrarlana bilən obyektdə (hazırda Kolleksiyada) hələ də dəyərlər qalırsa, truedaha çox dəyər yoxdursa, metod geri qayıdacaq false. E next()— kolleksiyanın (obyektin) növbəti elementini qaytarır. Artıq element yoxdursa (heç bir çek yox idi hasNext()və biz next()kolleksiyanın sonuna çatdıqda zəng etdik), üsul atacaq NoSuchElementException. void remove()- sonuncu tərəfindən əldə edilmiş elementi siləcək next(). Metod ata bilər:
  • UnsupportedOperationException, əgər bu iterator metodu dəstəkləmirsə remove()(məsələn, yalnız oxunan kolleksiyalar vəziyyətində)
  • IllegalStateException, əgər metod next()hələ çağırılmayıbsa və ya remove()son zəngdən sonra artıq çağırılıbsa next().
Beləliklə, List üçün iterator ən çox yayılmış tətbiqdir. İterator kolleksiyanın əvvəlindən sonuna qədər gedir: o, növbəti elementin olub-olmadığını yoxlayır və əgər varsa, onu qaytarır. Bu sadə alqoritm əsasında bir dövr qurulur for-each. Onun genişləndirilməsi ListIterator-dur. Əlavə java siyahısı iterator üsullarına baxaq. Çox güman ki, onları tanıyırsınız:
  • void add(E e)— element daxil Eedir ;List
  • boolean hasPrevious()— əks axtarış zamanı elementlər olarsa trueqayıdacaq ;List
  • int nextIndex()— növbəti elementin indeksini qaytaracaq;
  • E previous()— əvvəlki vərəq elementini qaytaracaq;
  • int previousIndex()— əvvəlki elementin indeksini qaytaracaq;
  • void set(E e)- son zənglə qaytarılan elementi next()və ya previous()elementlə əvəz edəcək e.
Kiçik bir misala baxaq. ListŞagirdlərə təbrik sətirlərini ehtiva edən bir yazı yaradaq :
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Обучающимся");
list.add("На");
list.add("JavaRush");
İndi bunun üçün bir iterator alacağıq və bütün daxil olan sətirləri konsola çap edəcəyik:
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
İndi bir "darboğaz" olacaq: Java Kolleksiyaları, yəqin ki, bildiyiniz kimi (və bilmirsinizsə, anlayın), interfeysi genişləndirin Iterable, lakin bu, yalnız o demək deyil ki List, Setiteratoru Queuedəstəkləyir. For java Map iteratorda dəstəklənir, lakin çağırılmalıdır Map.entrySet():
Map<String, Integer> map = new HashMap<>();
Iterator mapIterator = map.entrySet().iterator();
Sonra metod “açar”-“dəyər” cütünü ehtiva edən next() obyekti qaytaracaq . EntrySonra hər şey eynidir List:
while (mapIterator.hasNext()) {
    Map.Entry<String, Integer> entry = mapIterator.next();
    System.out.println("Key: " + entry.getKey());
    System.out.println("Value: " + entry.getValue());
}
Düşünürsən: “Dayan. Söhbət interfeysdən gedir və məqalənin başlığında “Nümunə” deyilir. Yəni, iterator nümunəsi İterator interfeysidir? Yoxsa interfeys nümunədir? Bu söz ilk dəfə görünürsə, mən sizə istinad verirəm: naxış dizayn nümunəsidir, bir sinifin və ya bir-biri ilə əlaqəli bir çox sinifin riayət etməli olduğu müəyyən bir davranışdır. Java-da iterator daxili strukturu təkrarlamağı nəzərdə tutan istənilən obyekt üçün həyata keçirilə bilər və siz müzakirə olunan metodların imzasını dəyişə bilərsiniz. Nümunəni həyata keçirərkən əsas şey sinifin riayət etməli olduğu məntiqdir. İterator interfeysi həm hazır strukturlara ( List, Set, Queue, Map), həm də proqramçının mülahizəsinə uyğun olaraq digərlərinə tətbiq edilən eyniadlı nümunənin özəl həyata keçirilməsidir. İterator interfeysini genişləndirməklə siz nümunəni həyata keçirirsiniz, lakin nümunəni həyata keçirmək üçün interfeysi genişləndirməyə ehtiyac yoxdur. Sadə bir bənzətmə: bütün balıqlar üzür, amma üzən hər şey balıq deyil. Nümunə olaraq... sözü götürmək qərarına gəldim. Daha dəqiq desək, isim. O, hissələrdən ibarətdir: prefiks, kök, şəkilçi və sonluq. Sözün hissələri üçün biz interfeys WordPartvə onu genişləndirən siniflər yaradacağıq: Prefix, Root, Suffix и Ending:
interface WordPart {
    String getWordPart();
}

static class Root implements WordPart {

    private String part;

    public Root(String part) {
        this.part = part;
    }

    @Override
    public String getWordPart() {
        return part;
    }
}

static class Prefix implements WordPart {

    private String part;

    public Prefix(String part) {
        this.part = part;
    }

    @Override
    public String getWordPart() {
        return part;
    }
}

static class Suffix implements WordPart {

    private String part;

    public Suffix(String part) {
        this.part = part;
    }

    @Override
    public String getWordPart() {
        return part;
    }
}

static class Ending implements WordPart {

    private String part;

    public Ending(String part) {
        this.part = part;
    }

    @Override
    public String getWordPart() {
        return part;
    }
}
Sonra sinifdə Word(sözdə) hissələr olacaq və onlara əlavə olaraq sözdəki hissələrin sayını əks etdirən tam ədəd əlavə edəcəyik:
public class Word {

    private Root root;
    private Prefix prefix;
    private Suffix suffix;
    private Ending ending;
    private int partCount;

    public Word(Root root, Prefix prefix, Suffix suffix, Ending ending) {
        this.root = root;
        this.prefix = prefix;
        this.suffix = suffix;
        this.ending = ending;
        this.partCount = 4;
    }

    public Word(Root root, Prefix prefix, Suffix suffix) {
        this.root = root;
        this.prefix = prefix;
        this.suffix = suffix;
        this.partCount = 3;

    }

    public Word(Root root, Prefix prefix) {
        this.root = root;
        this.prefix = prefix;
        this.partCount = 2;
    }

    public Word(Root root) {
        this.root = root;
        this.partCount = 1;
    }

    public Root getRoot() {
        return root;
    }

    public Prefix getPrefix() {
        return prefix;
    }

    public Suffix getSuffix() {
        return suffix;
    }

    public Ending getEnding() {
        return ending;
    }

    public int getPartCount() {
        return partCount;
    }

    public boolean hasRoot() {
        return this.root != null;
    }

    public boolean hasPrefix() {
        return this.prefix != null;
    }

    public boolean hasSuffix() {
        return this.suffix != null;
    }

    public boolean hasEnding() {
        return this.ending != null;
    }
Yaxşı, bizdə dörd həddən artıq yüklənmiş konstruktor var (sadəlik üçün fərz edək ki, bizdə yalnız bir şəkilçi ola bilər). İsim bir prefiksdən ibarət ola bilməz, ona görə də bir parametrli konstruktor üçün kök təyin edəcəyik. İndi iterator modelinin tətbiqini yazaq: WordIterator, 2 metodu üstələyən: hasNext()next():
public class WordIterator implements Iterator<Word.WordPart> {

    private Word word;
    private int wordPartsCount;

    public WordIterator(Word word) {
        this.word = word;
        this.wordPartsCount = word.getPartCount();
    }

    @Override
    public boolean hasNext() {
        if (wordPartsCount == 4) {
            return word.hasPrefix() || word.hasRoot() || word.hasSuffix() || word.hasEnding();
        } else if (wordPartsCount == 3) {
            return word.hasPrefix() || word.hasRoot() || word.hasSuffix();
        } else if (wordPartsCount == 2) {
            return word.hasPrefix() || word.hasRoot();
        } else if (wordPartsCount == 1) {
            return word.hasRoot();
        }
        return false;
    }

    @Override
    public Word.WordPart next() throws NoSuchElementException {
        if (wordPartsCount <= 0) {
            throw new NoSuchElementException("No more elements in this word!");
        }

        try {
            if (wordPartsCount == 4) {
                return word.getEnding();
            }
            if (wordPartsCount == 3) {
                return word.getSuffix();
            }
            if (wordPartsCount == 2) {
                return word.getPrefix();
            }
            return word.getRoot();
        } finally {
            wordPartsCount--;
        }
    }
}
Qalan yalnız iteratoru sinifə təyin etməkdir Word:
public class Word implements Iterable<Word.WordPart> {@Override
	public Iterator<WordPart>iterator() {
    		return new WordIterator(this);
	}}
İndi isə gəlin “tələs” sözünün morfemik təhlilini aparaq:
public class Main {
    public static void main(String[] args) {
        Word.Root root = new Word.Root("беж");
        Word.Prefix prefix = new Word.Prefix("пере");
        Word.Suffix suffix = new Word.Suffix("к");
        Word.Ending ending = new Word.Ending("a");

        Word word = new Word(root, prefix, suffix, ending);

        Iterator wordIterator = word.iterator();
        while (wordIterator.hasNext()) {
            Word.WordPart part = (Word.WordPart) wordIterator.next();
            System.out.println(part.getClass() + ": " + part.getWordPart());
        }
    }
}
Nəzərə alın ki, iterator modelini həyata keçirərkən mən aşağıdakı çıxış sırasını seçdim:
  1. sona çatır
  2. şəkilçi
  3. konsol
  4. kök
Öz iteratorunuzu tərtib edərkən, təkrarlama alqoritmini istədiyiniz kimi təyin edə bilərsiniz. Təhsilinizdə uğurlar!
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION