Собственный итератор JAVA
IterNap napis = new IterNap("prOgrAmoWanIe ObiEktOwe i Gui");
for (char z: napis)
System.out.print(z + " ");
В коде выше я создаю объект napis класса IterNap, а после в цикле for-each выписываю каждый символ. В результате должна получиться вот такая строка
p r O g r A m o W a n I e O b i E k t O w e i G u i
Задача: написать реализацию класса IterNap, использовать массивы и коллекции запрещено.
Вообще не понимаю как это реализовать. Смог только создать класс IterMap и унаследоваться от Itarable, но как переопределить итератор? Прошу помощи.
Ответы (2 шт):
В целом задача простая: понять как работает итератор. А работает он очень просто:
public class IteratorNap implements Iterator<Character> {
private String value;
private int pos;
public IteratorNap(String value) {
this.value = value;
}
@Override
public boolean hasNext() {
return pos < value.length();
}
@Override
public Character next() {
return value.charAt(pos++);
}
}
Как видно у итератора есть 2 метода: hasNext(), который проверяет есть ли еще данные и next() который возвращает эти данные.
Имея этот класс уже можно составить замысловатую конструкцию перебора:
for (IteratorNap it = new IteratorNap("Hello world!"); it.hasNext(); ) {
char character = it.next();
System.out.print(character + " ");
}
Но чтобы избежать эту конструкцию и получить более знакомый формат перебора, нужно реализовать интерфейс Iterable:
public static class IterableNap implements Iterable <Character> {
private String value;
public IterableNap(String value) {
this.value = value;
}
@Override
public Iterator<Character> iterator() {
return new IteratorNap(this.value);
}
}
Я думаю тут всё понятно без объяснений.
В итоге мы получаем следующее:
IterableNap nap = new IterableNap("Hello world!");
for(char character : nap) {
System.out.print(character + " ");
}
>> H e l l o w o r l d !
Почитайте документацию по Interface Iterator<E> (читать), поймите, что ожидается от выполнения методов этого интерфейса (их контракт) и реализуйте. Ваш IterNap принимает строку в конструкторе, использовать массивы и коллекции нельзя, судя по вводу/выводу, вы будете итерироваться по строке (по символам строки). Полагаю, что для вашей задачи хватит реализовать 2 метода: hasNext() и next(). Ниже вариант сделанный на скорую руку и в нём есть что можно улучшить, но для понимания, как решать такие задачи достаточно.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class IterNap implements Iterable<Character> {
// Строка по которой итерируемся
private final String inputString;
// Конструктор получающий строку
public IterNap(String inputString) {
this.inputString = inputString;
}
// Реализовали метод Iterable для получения итератора (в нашем случае это инстанс вложенного класса ImplIterator, имплементирующего интерфейс Iterator)
@Override
public Iterator iterator() {
return new ImplIterator();
}
// Класс ImplIterator, имплементирующий интерфейс Iterator
private class ImplIterator implements Iterator<Character> {
// Это текущий элемент в итераторе и одновременно счётчик
int current = 0;
// Возвращает true, если есть следующий элемент (символ)
@Override
public boolean hasNext() {
if (current == inputString.length()) { // простая проверка - если текущий элемент равен количеству символов в строке, то есть
// указвает на последний символ в строке, значит следущий элемент отсутствует и вернём false
return false;
}
return true;
}
// Возвращает следующий элемент в итерации (символ)
@Override
public Character next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return inputString.charAt(current++);
}
}
public static void main(String... args) {
IterNap napis = new IterNap("prOgrAmoWanIe ObiEktOwe i Gui");
for (char z : napis) {
System.out.print(z + " ");
}
}
}