#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