Бүгүн биз Java'да Iterator деген эмне жана ал эмне үчүн керек экендиги жөнүндө сүйлөшөбүз .
Сиз билгендей, Javaда Iterator интерфейсин ишке ашырган сонун Collection интерфейси бар. Мага дароо ээлеп коюуга уруксат этиңиз: итератор интерфейсин Javaдагы итератор үлгүсү менен чаташтырбоо керек! Ал эми тактоо үчүн, адегенде интерфейсти карап көрөлү.
Келгиле, бир секундага Javaда итератор жок экенин элестетип көрөлү. Бул учурда, ар бир адам коллекциялардын тереңине сүңгүп, эмнеси менен айырмаланарын чындап
Сөзмө-сөз, "Итератор" "кара күч " деп которулса болот . Башкача айтканда, бул коллекциядагы бардык элементтерди кайталай турган белгилүү бир нерсе. Мындан тышкары, бул коллекциялардын ички түзүмүн жана тартибин изилдебестен жасоого мүмкүндүк берет. |
ArrayList
түшүнүшү керек . LinkedList
HashSet
TreeSet
Итератор ишке ашырууга тийиш болгон ыкмалар
boolean hasNext()
— эгерде кайталануучу an objectте дагы деле маанилер болсо (учурда Коллекция), true
эгер башка маанилер жок болсо, метод кайтып келет false
. E next()
— коллекциянын (an objectтин) кийинки элементин кайтарат. Эгер дагы элементтер жок болсо (чек болгон жок жана биз коллекциянын аягына жеткенде hasNext()
чакырдык ), ыкма ыргытат . - акыркы жолу алынган элементти алып салат . Метод ыргыта алат: next()
NoSuchElementException
void remove()
next()
UnsupportedOperationException
, эгерде бул итератор методду колдоого албасаremove()
(мисалы, окуу үчүн гана жыйнактарда)IllegalStateException
, эгерде методnext()
али чакырыла элек болсо же алremove()
акыркы чакыруудан бери чакырылсаnext()
.
for-each
. Анын кеңейтorши ListIterator болуп саналат. Келгиле, кошумча Java тизмеси итератор ыкмаларын карап көрөлү. Сиз аларды билесиз:
void add(E e)
— элементтиE
киргизет ;List
boolean hasPrevious()
— тескери издөө учурунда элементтер барtrue
болсо кайтарып берет ;List
int nextIndex()
— кийинки элементтин индексин кайтарат;E previous()
— мурунку барак элементин кайтарат;int previousIndex()
— мурунку элементтин индексин кайтарат;void set(E e)
next()
- акыркы чалуу жеprevious()
элемент менен кайтарылган элементти алмаштыратe
.
List
студенттерге саламдашуу саптарын түзөлү:
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Обучающимся");
list.add("На");
list.add("JavaRush");
Эми биз ал үчүн итераторду алабыз жана бардык камтылган саптарды консолго басып чыгарабыз:
Iterator iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
Эми "тоскоолдук" пайда болот: Java Collections, сиз билгендей (жана билбесеңиз, аны тактаңыз), интерфейсти кеңейтүү , бирок бул бир гана итераторду колдойт дегенди Iterable
билдирбейт . For да колдоого алынат, бирок чакырылышы керек : List
Set
Queue
java Map iterator
Map.entrySet()
Map<String, Integer> map = new HashMap<>();
Iterator mapIterator = map.entrySet().iterator();
Андан кийин ыкма "ачкыч" - "маани" жупту камтыган next()
an objectти кайтарат . Entry
Ошондо баары бирдей List
:
while (mapIterator.hasNext()) {
Map.Entry<String, Integer> entry = mapIterator.next();
System.out.println("Key: " + entry.getKey());
System.out.println("Value: " + entry.getValue());
}
Сиз ойлойсуз: «Токто. Кеп интерфейс жөнүндө болуп жатат жана макаланын аталышында "Үлгү" деп айтылат. Башкача айтканда, итератор үлгүсү Итератор интерфейсиби? Же интерфейс үлгүбү? Бул сөз биринчи жолу пайда болсо, мен сизге шилтеме берем: үлгү - бул дизайн үлгүсү, класс же көптөгөн өз ара байланышкан класстар карманууга тийиш болгон белгилүү бир жүрүм-турум. Java тorнде итератор ички түзүмү итерациялоону камтыган ар кандай an object үчүн ишке ашырылышы мүмкүн жана талкууланган ыкмалардын кол тамгасын өзгөртүүгө болот. Үлгү ишке ашырууда негизги нерсе класс карманууга тийиш болгон логика. Итератор интерфейси – бул даяр структураларга ( List, Set, Queue, Map
) да, башкаларына да программисттин кароосу боюнча колдонулуучу бир эле аталыштагы үлгүнүн жеке ишке ашырылышы. Iterator интерфейсин кеңейтүү менен сиз үлгүнү ишке ашырасыз, бирок үлгүнү ишке ашыруу үчүн интерфейсти кеңейтүүнүн кереги жок. Жөнөкөй окшоштук: бардык балыктар сүзүшөт, бирок сүзгөндөрдүн баары эле балык эмес. Мисал катары мен... сөздү алууну чечтим. Тагыраак айтканда, зат атооч. Ал бөлүктөн турат: префикс, уңгу, суффикс жана аягы. WordPart
Сөздүн бөлүктөрү үчүн интерфейсти жана аны кеңейтүүчү класстарды түзөбүз : 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;
}
}
Андан кийин класс Word
(сөз) бөлүктөрдү камтыйт жана аларга кошумча түрдө сөздөгү бөлүктөрдүн санын чагылдырган бүтүн санды кошобуз:
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;
}
Макул, бизде төрт ашыкча конструктор бар (жөнөкөйлүк үчүн, бизде бир гана суффикс болушу мүмкүн деп коёлу). Зат атооч бир префикстен турушу мүмкүн эмес, ошондуктан бир параметри бар конструктор үчүн тамырды орнотобуз. Эми итератор үлгүсүн ишке ашырууну жазалы: WordIterator, 2 ыкманы жокко чыгарат: 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--;
}
}
}
Итераторду класска дайындоо гана калды Word
:
public class Word implements Iterable<Word.WordPart> {
…
@Override
public Iterator<WordPart>iterator() {
return new WordIterator(this);
}
…
}
Эми “шаш” сөзүнө морфемикалык анализ жасайлы:
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());
}
}
}
Сураныч, итератор үлгүсүн ишке ашырууда мен төмөнкү чыгаруу тартибин тандадым:
- бүтүрүү
- суффикс
- консол
- тамыр
GO TO FULL VERSION