Подтвердить что ты не робот

Итератор против

В интервью мне было предложено узнать, в чем преимущество использования итератора, использующего цикл for или что является преимуществом использования для цикла над итератором?

Может ли любой орган ответить на это, чтобы в будущем. Если я столкнусь с подобным вопросом, тогда я могу ответить на этот вопрос.

4b9b3361

Ответ 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 быстрый, забавный, но вы не можете использовать его в тяжелую зиму или во время дождя, вы не можете носить с собой большие предметы, это тоже загрязняет, и это довольно опасно в пробке.

Что лучше? Нет однозначного ответа, это зависит от ситуации, так как цель (идти на работу) одинакова. Вы должны точно знать, каковы условия окружающей среды, что вы должны носить и т.д.

То же самое с итераторами против циклов. В одном случае у вас есть видимые структурные элементы, которые вы можете использовать; в другом случае вы их не видите, но у вас более компактный вид. Поэтому вы должны оценить, какой из них лучше в зависимости от состояния окружающей среды, что вы должны носить и т.д.:)