Чем iterator отличается от цикла for в Java?

382
03 января 2018, 18:52

Объясните, пожалуйста, в каких случаях итератор лучше цикла? Еще мне интересно как в итераторе я могу задать сортировку элементов массива, например, по алфавиту или по конкретной букве.

Answer 1

Итератор не лучше цикла. Итератор - способ перебрать все элементы какой-либо сущности. А цикл не обязательно что-то перебирает. Например, while (true){} не перебирает ничего. Цикл для простоты понимания лучше рассматривать, как хождение по кругу. Причем этот круг может вообще намертво замкнуться и цикл станет бесконечным. Сравним два применения цикла:

Когда вы делаетет так

ArrayList <String> list = new Arraylist <>();
for (int i=0; i<list.size(); i++)System.out.printl(list [i]);

И так

ArrayList <String> list = new Arraylist <>();
for (String s : list) System.out.printl(s);

На вид происходит тоже самое, а на самом деле - это принципиально разный код. Во втором случае вы используете итератор, просто неявно. Его использует сокращенный цикл for. В первом случае вы используете особенности реализации ArrayList , а именно то, что в ArrayList есть индексы, по которым можно получить доступ к элементам ArrayList. Здесь итератор, который имплементируется коллекций, не вызывается, а цикл просто перебирает все натуральные числа от 0 до тех пор, пока это самое натуральное число не станет равным длине коллекции, тогда цикл прерывается. Посему перебрать, например коллекцию типа сет, первым способом вы уже не сможете, ведь индексов у сета нет, а вот вторым без проблем, потому как сет имплементирует итератор.

Исходя из сказанного, становится понятно, что сортировка элементов тут не причем. Назначение итератора, как уже было сказано, - перебрать все элементы сущности. Если вам нужна сортировка, то существует другая замечательная штука, называемая компаратор, но сейчас не об этом. Итератор - не средство сортировки. Вы должны понимать, что мы говорим об интерфейсе, имплементировать который могут классы с абсолютно разной логикой. К примеру, коллекция HashSet не гарантирует порядок элементов и вы никак не можете их упорядочить в пределах этой коллекции. Соответственно итератор, как интерфейс, невозможно приспособить для таких задач. Сущность, его имплементирующая, может просто не поддерживать сортировку элементов в принципе в виду особенности своей внутренней логики, как HashSet.

И последнее... Вызывать итератор в явном виде зачастую нецелесообразно и делается это, как правило в одном случае - когда во время итерации вам нужно удалять элементы. У итератора есть методы hasNext, next и remove, которые проверяют наличие следующего элемента, получает следующий элемент и удаляет элемент соотвественно. Попытка удаления элемента при итерации с помощью цикла приведет к исключению. Причем исключение будет брошено даже, если вы используетет сокращенный цикл типа for (String s : list). Происходит это потому, что хотя этот цикл неявно и использует итератор, но у вас нет к нему доступа. Соответственно, единственный доступный вам способ удалить элементы - вызывать метод remove у коллекции list, что приведет к исключению, ведь для удаления элементов во время итерации по ней нужно вызывать метод remove не у коллекции list, а у самого итератора, к которому, как уже было сказано, у вас в любом из циклов доступа нет.

И еще... В предыдущем абзаце сказано что итератор, как правило, вызывается в одном случае. На самом деле не в одном. Просто зачастую он вызывается именно для указанного случая. А вот остальные случаи вам придется изучить самостоятельно, так как их назначение не столь тривиально, чтобы объяснить это в таком контексте. Речь идет, например, о том, что у одного объекта может быть вызвано несколько итераторов, которым задана разная логика работы... Но это придет со временем

READ ALSO
Свойство &ldquo;overflow&rdquo;

Свойство “overflow”

Я уже гуглил на счёт этого свойства, я вроде-бы понимаю смысл его действия, но не всегдаОбъясните: что оно конкретно делает з float элементами,...

310
Путь к изображению в другой директории при вызове через include

Путь к изображению в другой директории при вызове через include

Приветствую, иметься директория, в ней:

287