2013-02-23 3 views
2

Я знаю, что переборе LinkedList с помощьюРазличие в Переборе связных списков

for(int i = 0; i < list.size(); i++){ 
    Item item = list.get(i); 
} 

, чтобы получить отдельные объекты имеют плохую производительность, как каждый вызов .get (я) перебирает от начала списка до я.

Правильный способ использования Итератора. Все идет нормально.

Но что об этом стиле:

for(Item item : list){ 
    // item is already here 
} 

ли это иметь такую ​​же производительность, как с помощью итераторов? Как это работает внутри страны?

+0

Вы можете реализовать LinkedList w hich не имеет плохой производительности, используя старый стиль loop и list.get (i). Просто кешируйте последний доступ к узлу в надежде, что следующий вызов будет непосредственно следующим узлом в списке.Это приведет к аналогичной производительности, такой как использование итератора. – MrSmith42

+0

Возможный дубликат [Как работает Java для каждого цикла?] (Http://stackoverflow.com/questions/85190/how-does-the-java-for-each-loop-work) –

ответ

3

Имеет ли такое же значение, как итераторы?

Да. Оба варианта генерируют один и тот же байт-код. Следующий байт-код был создан из-за каждой петли, но при использовании итератор в цикле он выглядит точно так же:

for(Object o : list) { 
} 

    44: aload_1 
    45: invokevirtual #30     // Method java/util/LinkedList.iterator:()Ljava/util/Iterator; 
    48: astore_3 
    49: goto   59 
    52: aload_3 
    53: invokeinterface #34, 1   // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object; 
    58: astore_2 
    59: aload_3 
    60: invokeinterface #40, 1   // InterfaceMethod java/util/Iterator.hasNext:()Z 
    65: ifne   52 

Как это работает внутри?

В случае не-массивов, для каждого цикла используются итераторы внутри. См. Выше код байта - вызывается все методы, которые также будут вызываться при использовании Iterator.

См. Также The For-Each Loop и How does the Java 'for each' loop work? для получения дополнительной информации.

+0

Спасибо большое! Это именно то, что я хотел знать :) – Smashnet

2

Контур foreach использует интерфейс Iterable. Он вызывает iterator() и выполняет итерацию с помощью итератора. Специальная обработка используется для массивов.

0

Для каждого цикла используется одно отличие, если вы не хотите изменять список size. потому что он использует iterators, которые становятся invalidate после resize списка. Если это не так в нормальном для цикла. Но standard loop звоните size функции каждый раз, что делает его менее эффективным, чем for each. Чтобы получить такую ​​же производительность, вам нужно поставить значение constant, например 10,15, .. и т. Д. В состоянии standard loop.

  • Для каждого - только для чтения режима

  • Standard For - Чтение и запись Оба

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

+0

Вызов 'size()' не является неэффективной частью традиционного цикла 'for' с' LinkedList', это вызов 'get (i)', который делает его медленным. 'get (i)' внутренне итерации от первого до 'i' на каждом вызове, тогда как итератор запоминает текущую позицию и переходит к следующему элементу за один шаг. – jlordo

+0

Я, это правда, но я говорю только для разницы. – Arpit

+0

Вопрос OPs явно о 'LinkedList'. Общий ответ «Список» не кажется полезным. Ваше утверждение о том, что использование константного значения вместо 'size()' для получения одинаковой производительности является неправильным из-за того, что реализовано «LinkedList». – jlordo

Смежные вопросы