JavaRush /Blog Java /Random-MS /Corak iterator

Corak iterator

Diterbitkan dalam kumpulan
Hari ini kita akan bercakap tentang apa itu Iterator di Jawa dan mengapa ia diperlukan.
Corak iterator - 1
Seperti yang anda mungkin sedia maklum, Java mempunyai antara muka Koleksi yang menarik yang melaksanakan antara muka Iterator. Biar saya membuat tempahan dengan segera: antara muka lelaran tidak boleh dikelirukan dengan corak lelaran di Jawa! Dan untuk menjelaskannya, mari kita lihat antara muka dahulu.
Secara harfiah, "Iterator" boleh diterjemahkan sebagai "kekerasan . " Iaitu, entiti tertentu yang boleh lelaran melalui semua elemen dalam koleksi. Selain itu, ia membolehkan anda melakukan ini tanpa menyelidiki struktur dalaman dan susunan koleksi.
Mari kita bayangkan sejenak bahawa tiada iterator di Jawa. Dalam kes ini, setiap orang perlu menyelami kedalaman koleksi dan benar-benar memahami apa yang berbeza ArrayListdaripada LinkedListdan HashSetdaripada TreeSet.

Kaedah yang mesti dilaksanakan oleh Iterator

boolean hasNext()— jika masih ada nilai yang tinggal dalam objek boleh lelar (kini Koleksi), kaedah akan kembali true, jika tiada lagi nilai false. E next()— mengembalikan elemen koleksi seterusnya (objek). Jika tiada lagi elemen (tiada semak hasNext(), dan kami memanggil next()apabila kami sampai ke penghujung koleksi), kaedah itu akan membuang NoSuchElementException. void remove()- akan mengalih keluar elemen yang terakhir diperolehi oleh next(). Kaedah boleh membuang:
  • UnsupportedOperationException, jika iterator ini tidak menyokong kaedah remove()(dalam kes koleksi baca sahaja, contohnya)
  • IllegalStateException, jika kaedah itu next()belum lagi dipanggil, atau jika ia remove()telah dipanggil sejak panggilan terakhir next().
Jadi, iterator untuk Senarai adalah pelaksanaan yang paling biasa. Peulang pergi dari permulaan koleksi hingga penghujungnya: ia melihat untuk melihat sama ada elemen seterusnya hadir dan mengembalikannya jika ada. Satu kitaran dibina berdasarkan algoritma mudah ini for-each. Sambungannya ialah ListIterator. Mari lihat kaedah iterator senarai java tambahan. Anda berkemungkinan besar mengenali mereka:
  • void add(E e)— memasukkan elemen Eke dalam ;List
  • boolean hasPrevious()— akan kembali truejika Listterdapat unsur semasa carian terbalik;
  • int nextIndex()— akan mengembalikan indeks elemen seterusnya;
  • E previous()— akan mengembalikan elemen helaian sebelumnya;
  • int previousIndex()— akan mengembalikan indeks elemen sebelumnya;
  • void set(E e)- akan menggantikan elemen yang dikembalikan oleh panggilan terakhir next()atau previous()dengan elemen e.
Mari kita lihat contoh kecil. Mari kita buat yang Listmengandungi baris ucapan kepada pelajar:
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Обучающимся");
list.add("На");
list.add("JavaRush");
Sekarang kita akan mendapatkan iterator untuknya dan mencetak semua baris yang terkandung ke konsol:
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}
Sekarang akan ada "sekatan": Java Collections, seperti yang anda mungkin tahu (dan jika anda tidak tahu, fikirkan), lanjutkan antara muka Iterable, tetapi ini tidak bermakna hanya List, Setdan Queuemenyokong iterator. Untuk java Map iteratorjuga disokong, tetapi mesti dipanggil untuk Map.entrySet():
Map<String, Integer> map = new HashMap<>();
Iterator mapIterator = map.entrySet().iterator();
Kemudian kaedah next() akan mengembalikan objek Entryyang mengandungi pasangan "kunci" - "nilai". Kemudian semuanya sama dengan List:
while (mapIterator.hasNext()) {
    Map.Entry<String, Integer> entry = mapIterator.next();
    System.out.println("Key: " + entry.getKey());
    System.out.println("Value: " + entry.getValue());
}
Anda berfikir: "Berhenti. Kami bercakap tentang antara muka, dan tajuk artikel mengatakan "Corak". Iaitu, corak iterator ialah antara muka Iterator? Atau adakah antara muka satu corak? Jika perkataan ini muncul buat kali pertama, saya memberi anda rujukan: corak ialah corak reka bentuk, tingkah laku tertentu yang mesti dipatuhi oleh kelas atau banyak kelas yang saling berkaitan. Iterator dalam java boleh dilaksanakan untuk mana-mana objek yang struktur dalamannya melibatkan lelaran, dan anda boleh menukar tandatangan kaedah yang dibincangkan. Perkara utama apabila melaksanakan corak ialah logik yang mesti dipatuhi oleh kelas. Antara muka iterator ialah pelaksanaan peribadi corak dengan nama yang sama, digunakan untuk kedua-dua struktur siap ( List, Set, Queue, Map), dan kepada yang lain, mengikut budi bicara pengaturcara. Dengan memanjangkan antara muka Iterator, anda melaksanakan corak, tetapi anda tidak perlu melanjutkan antara muka untuk melaksanakan corak. Analogi mudah: semua ikan berenang, tetapi tidak semua yang berenang adalah ikan. Sebagai contoh, saya memutuskan untuk mengambil... perkataan itu. Lebih khusus, kata nama. Ia terdiri daripada bahagian: awalan, akar, akhiran dan akhir. Untuk bahagian perkataan, kami akan mencipta antara muka WordPartdan kelas yang memanjangkannya: 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;
    }
}
Kemudian kelas Word(perkataan) akan mengandungi bahagian, dan sebagai tambahan kepada mereka kami akan menambah integer yang mencerminkan bilangan bahagian dalam perkataan:
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;
    }
Okay, kita mempunyai empat pembina yang terlebih beban (untuk kesederhanaan, mari kita anggap kita hanya boleh mempunyai satu akhiran). Kata nama tidak boleh terdiri daripada satu awalan, jadi untuk pembina dengan satu parameter kita akan menetapkan akarnya. Sekarang mari kita tulis pelaksanaan corak iterator: WordIterator, mengatasi 2 kaedah: hasNext()dan 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--;
        }
    }
}
Apa yang tinggal adalah untuk menetapkan iterator kepada kelas Word:
public class Word implements Iterable<Word.WordPart> {@Override
	public Iterator<WordPart>iterator() {
    		return new WordIterator(this);
	}}
Sekarang mari kita jalankan analisis morfem perkataan "tergesa-gesa":
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());
        }
    }
}
Sila ambil perhatian bahawa dalam pelaksanaan corak iterator saya, saya memilih susunan output berikut:
  1. berakhir
  2. akhiran
  3. konsol
  4. akar
Apabila mereka bentuk lelaran anda sendiri, anda boleh menentukan algoritma lelaran mengikut kehendak anda. Semoga berjaya dalam pelajaran anda!
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION