Почему у итератора нет никакого метода сброса?

#java #collections #iterator

#java #Коллекции #итератор

Вопрос:

Почему? И каков наилучший способ переместить указатель элементов итератора в первую позицию?

Ответ №1:

Почему?

Потому что, если вы заставляете итератор использовать метод сброса, у каждого итератора должен быть метод сброса. Это дает каждому автору итератора дополнительную работу. Кроме того, некоторые итераторы действительно сложно (или очень дорого) сбросить, и вы бы не хотели, чтобы пользователи вызывали reset на них. Хорошими примерами являются итераторы над файлами или потоками.

каков наилучший способ переместить указатель элементов итератора в первую позицию?

Создайте новый итератор. Это редко дороже, чем сброс.

Комментарии:

1. (За исключением того факта, что существует remove метод, который на самом деле не дает всем итераторам «дополнительную работу», поскольку операция необязательна.)

2. @aioobe Бывают случаи, когда удаление текущего объекта с помощью итератора действительно упрощает жизнь разработчикам. Существует очень мало случаев, когда это верно для сброса (потому что вы почти всегда можете создать новый итератор).

3. @DJClayworth «Это дает каждому автору итератора дополнительную работу». Это не разумный ответ. Разработчикам библиотек нужно приложить немного дополнительных усилий, но выигрыш в том, что многие пользователи библиотеки получат выгоду.

4. Гораздо более важным моментом является второй, что некоторые итераторы невозможно сбросить.

5. Что, если итератор является параметром метода? Если я хочу, чтобы изменения в итераторе распространялись на вызывающий метод… Я просто не могу, верно?

Ответ №2:

Прочитав поток, вы не сможете перечитать его, не открыв исходный код снова. Вот как работают потоки и итераторы.

Ответ №3:

Лучший способ — создать новый!

Комментарии:

1. Точно так же, как вы создали предыдущий: Iterator<T> iterator = iteratable. iterator();

Ответ №4:

Это общая тенденция, принятая в JCF — сохранять минималистичный интерфейс, если это не делает какую-либо функцию чрезвычайно сложной для работы. Это причина, по которой у вас нет отдельных интерфейсов для семантики, таких как неизменяемые коллекции, коллекции фиксированного размера..

Что касается того, почему тогда предоставляется remove(Object) (как необязательный) — Отсутствие этого сделало бы невозможным безопасное удаление элемента из коллекции во время итерации по коллекции — нет ничего, что делает предоставление reset() таким обязательным.

Опять же, почему существует отдельный ListIterator() (предоставляющий такие методы, как previous() и previousIndex() ) — С List интерфейсом , основной функциональностью при его использовании является возможность компоновки элементов по индексу и возможность доступа к ним в порядке индекса, будь то фиксированный или случайный порядок. Это не относится к другим коллекциям.Отсутствие этого интерфейса для List очень затруднит, если вообще возможно, бесперебойную работу со списком.

Комментарии:

1. Есть несколько вещей, которые можно сделать практически с любым Iteratable и Iterator , которые могли бы быть с пользой включены в интерфейс, но не были. Полезные методы итератора будут включать skip [эквивалент N последовательных вызовов перемещения, хотя многие итераторы могли бы реализовать его за время O (1)] и copyLocation [который вернет итератор, который, как ожидается, выдаст те же элементы, что и оригинал]. Любой итератор может реализовать skip метод, и любой не очень большой конечный итератор может реализовать copyLocation , перечислив себя в массив, а затем получив и его, и копию…

2. …возвращает элементы из этого массива. Клиентский код может выполнить любую операцию сам, но если итератор обладает специальными знаниями о своей внутренней работе, которых не хватает клиентскому коду, он может использовать эти знания для улучшения скорости на много порядков.

Ответ №5:

Совет: вместо этого создайте переменную итератора в виде функции, затем вы можете использовать ее столько раз, сколько захотите. Это работает, только если базовая логика повторяема.

Пример в Scala (Java похож, но у меня нет Java REPL под рукой)

 def i = (1 to 100) iterator   // i is our iterator
i.grouped(50) foreach println // prints two groups
i.grouped(50) foreach println // prints same two groups again