Итератор против
В интервью мне было предложено узнать, в чем преимущество использования итератора, использующего цикл for или что является преимуществом использования для цикла над итератором?
Может ли любой орган ответить на это, чтобы в будущем. Если я столкнусь с подобным вопросом, тогда я могу ответить на этот вопрос.
Ответы
Ответ 1
Прежде всего, есть 2 вида циклов for, которые ведут себя совершенно по-разному. Один использует индексы:
for (int i = 0; i < list.size(); i++) {
Thing t = list.get(i);
...
}
Такой цикл не всегда возможен. Например, списки имеют индексы, а наборы - нет, потому что они неупорядоченные коллекции.
Другой цикл foreach использует итератор за кулисами:
for (Thing thing : list) {
...
}
Это работает со всеми типами итеративной коллекции (или массива)
И, наконец, вы можете использовать Iterator, который также работает с любым Iterable:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
...
}
Таким образом, у вас фактически есть 3 цикла для сравнения.
Вы можете сравнить их в разных терминах: производительность, читаемость, вероятность ошибок, возможности.
Итератор может делать то, что не может цикл foreach. Например, вы можете удалять элементы во время итерации, если итератор поддерживает это:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
Thing t = it.next();
if (shouldBeDeleted(thing) {
it.remove();
}
}
Списки также предлагают итераторы, которые могут повторяться в обоих направлениях. Цикл foreach повторяется только от начала до конца.
Но Итератор более опасен и менее читабелен. Когда цикл foreach - это все, что вам нужно, это наиболее читаемое решение. С помощью итератора вы можете сделать следующее, что будет ошибкой:
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
System.out.println(it.next().getFoo());
System.out.println(it.next().getBar());
}
Цикл foreach не допускает возникновения такой ошибки.
Использование индексов для доступа к элементам несколько более эффективно с коллекциями, поддерживаемыми массивом. Но если вы передумаете и будете использовать LinkedList вместо ArrayList, внезапно производительность будет ужасной, потому что каждый раз, когда вы получаете доступ к list.get(i)
, связанный список должен будет проходить по всем его элементам до i-го. Итератор (и, следовательно, цикл foreach) не имеет этой проблемы. Он всегда использует наилучший из возможных способов перебора элементов данной коллекции, поскольку у самой коллекции есть собственная реализация Iterator.
Мое общее правило: используйте цикл foreach, если вам действительно не нужны возможности итератора. Я использовал бы только цикл с индексами с массивами, когда мне нужен доступ к индексу внутри цикла.
Ответ 2
Преимущество Iterator:
- Возможность удаления элементов из коллекций.
- Возможность перемещения вперед и назад с помощью
next()
и previous()
.
- Возможность проверить, есть ли другие элементы или нет, используя
hasNext()
.
Loop был разработан только для итерации по Collection
, поэтому, если вы хотите просто выполнить итерацию по Collection
, лучше использовать цикл, например for-Each
, но если вы хотите больше того, что вы могли бы использовать Iterator.
Ответ 3
если вы получаете доступ к данным по номеру (например, "i" ), это быстро, когда вы используете массив. потому что он напрямую связан с элементом
Но, другая структура данных (например, дерево, список), ей требуется больше времени, потому что она начинается с первого элемента на целевой элемент. когда вы используете список. Ему нужно время O (n). поэтому он должен быть медленным.
Если вы используете итератор, компилятор знает, где вы находитесь. так что ему нужно O (1)
(потому что он начинается с текущей позиции)
наконец, если вы используете только массив или структуру данных, которые поддерживают прямой доступ (например, arraylist в java). "a [i]" - это хорошо. но, когда вы используете другую структуру данных, итератор более эффективен
Ответ 4
Основное отличие между Iterator и классическим циклом, за исключением очевидного наличия или отсутствия доступа к индексу элемента, который вы повторяете, заключается в том, что с использованием Iterator абстрагирует код клиента из базовой реализации коллекции, позвольте мне уточнить.
Когда ваш код использует итератор, либо в этой форме
for(Item element : myCollection) { ... }
эта форма
Iterator<Item> iterator = myCollection.iterator();
while(iterator.hasNext()) {
Item element = iterator.next();
...
}
или эта форма
for(Iterator iterator = myCollection.iterator(); iterator.hasNext(); ) {
Item element = iterator.next();
...
}
Что говорит ваш код: "Меня не интересует тип коллекции и ее реализация, мне просто нужно, чтобы я мог выполнять итерацию по ее элементам". Как правило, это лучший подход, поскольку он делает ваш код более развязанным.
С другой стороны, если вы используете классический цикл for, как в
for(int i = 0; i < myCollection.size(); i++) {
Item element = myCollection.get(i);
...
}
В вашем коде говорится, что мне нужно знать тип коллекции, потому что мне нужно перебирать его элементы определенным образом, я также, возможно, собираюсь проверить нули или вычислить некоторый результат на основе порядка итерации, Это делает ваш код более хрупким, потому что если в какой-либо момент тип коллекции, которую вы получаете, изменится, это повлияет на то, как работает ваш код.
Подводя итог, разница заключается не столько в скорости, сколько в использовании памяти, это больше о развязывании кода, чтобы он был более гибким, чтобы справляться с изменениями.
Ответ 5
В отличие от других ответов, я хочу указать на другие вещи;
- Итератор - это концепция, а не реализация.
- Итератор предоставляет ряд операций для обхода и доступа к данным.
- Итератор может обернуть любую структуру данных, например массив.
- Одним из наиболее интересных и полезных преимуществ использования итераторов является возможность обертывания или декорирования другого итератора для фильтрации возвращаемых значений.
Ответ 6
В чем разница между использованием автомобиля, метро или вашего Vespa для работы? Автомобиль полезен, когда идет дождь, когда вам приходится носить с собой большие вещи, но вы будете тратить много времени на трафик и загрязнять его. Метро потрясающе, так как вам не нужно заботиться о дороге, трафике, загрязнении, но оно переполнено, и вы (вероятно) не найдете места, и если вы хотите что-то с собой понести, он не может быть слишком большим, Vespa быстрый, забавный, но вы не можете использовать его в тяжелую зиму или во время дождя, вы не можете носить с собой большие предметы, это тоже загрязняет, и это довольно опасно в пробке.
Что лучше? Нет однозначного ответа, это зависит от ситуации, так как цель (идти на работу) одинакова. Вы должны точно знать, каковы условия окружающей среды, что вы должны носить и т.д.
То же самое с итераторами против циклов. В одном случае у вас есть видимые структурные элементы, которые вы можете использовать; в другом случае вы их не видите, но у вас более компактный вид. Поэтому вы должны оценить, какой из них лучше в зависимости от состояния окружающей среды, что вы должны носить и т.д.:)