2009-12-01 2 views
4

Какая лучшая/предпочтительная идиома для декрементирующего цикла и почему?Лучшая идиома для декрементирующей петли

for(int idx=(len-1); idx>=0; idx--) {...} 

или

for(int idx=(len-1); idx>-1; idx--) {...} 

или (на основании ответа sylvarking, но используя для ограничить индекс сферы)

for(int idx=len; idx-->0;) {...} 

Является один или другой больше шансов подножку другого разработчика ?

+0

См. Также: http://stackoverflow.com/questions/1641054/what-are-the-advantages-for-count-down-and-count-up –

ответ

11

Я рекомендую следующее, потому что сравнение с нулем оптимизируется на уровне байтового кода.

for(int idx=(len-1); idx>=0; idx--) {...} 

Это предложение от Java Performance Tuning Джек Ширази

+2

Байт-коды обрабатываются далее, и вы не можете предсказать фактическое время работы, не зная, какой код будет выполнен в конце. Я считаю, что HotSpot очень хорошо приспособлен для оптимизации int i = 0; i

+0

Это правда Thorbjørn. Shirazi отмечает i n Настройка производительности Java, которую последние оптимизаторы VM оптимизируют для (int idx = 0; idx

0

Первый; это стандартный способ.

1

Я не могу сказать, что я когда-либо видел последнее, так что вот один голос за первый.

Не должно быть разницы в производительности.

Обратите внимание на то, что ваши петли повторяются по максимальным + 1 элементам. Обычно я ожидаю, что итерация от max-1 до 0.

+0

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

+1

Смотрите, слишком легко перепутаться :) Держитесь за стандартную 0..MAX - 1 идиому. –

+0

@Thorbjorn: На самом деле, я считаю, что это первый раз за 30 лет программирования. Я сделал эту ошибку, и это вполне вероятно, потому что я действительно работал над (другим) циклом включения, когда задавал вопрос, потому что видел уменьшающийся цикл в коде. –

1

Интересный вопрос! Лично я использую первый, и это тот, который я вижу больше всего для других программистов. Я думаю, причина в том, что люди привыкли тестировать нуль, а -1 могут их немного выбросить.

11

Другой массив-ориентированный вариант, который вы можете увидеть это:

int n = foo.length; 
while (n-- > 0) { 
    /* Do something with foo[n] */ 
} 

Из вариантов вы показать, я предпочитаю первый.

  • 0 это (возможно) более читаемым, чем -1.
  • Сравнение с нолем обычно быстрее, чем сравнение с другими константами. Это одна команда, которая рассматривает одно значение в стеке. В других сравнениях используется одна команда для вставки константы в стек и другая команда для сравнения двух верхних значений.
+2

Я тоже предпочитаю эту версию, хотя обычно я бы использовал для 'for (int i = a.length; i -> 0;)' idiom, если бы это был тривиальный обратный итератор, который не делал ничего умного с помощью или иметь дополнительный 'break'. – bobince

+0

Но, используя сравнение с нулевым кодом операции, нужно было бы idx! = 0 - то, чего я избегаю в принципе, потому что петли могут переполняться, если индекс изменяется нерегулярно (уменьшается или увеличивается более чем на 1, возможно, только при некоторых условиях) , –

+1

Нет, написанный, как я показал, достойный компилятор будет использовать код операции ifgt; есть код операции с нулевым значением для каждого отношения: 'ifeq',' ifne', 'iflt',' ifle', 'ifgt',' ifge'. – erickson

0

Второй по-прежнему меня смущает.
Первое (более или менее) то, что ожидает, в цикле декрементирования для цикла, нет необходимости проверять> -1, чтобы не иметь равных.

Лично я бы сделал как Mark Byers написал.

-1

я обнаружил, что для-петли с счетчиком должен только идти от нуля и до некоторого предела.

for(int i = 0; i < MAX; i++) { 
.... 
} 

Это настолько хорошо известно, что вы можете ожидать, что тот, кто видит это, сразу поймет, что происходит.Это также означает, что любое ОТКЛОНЕНИЕ из этой формы, считая назад или начинающееся с одного или наступая на три, затрудняет понимание, потому что вам нужно признать, что это разное, разобрать его и понять. Это включает в себя все ваши примеры.

Я хотел бы предложить писать это ясно:

for(int i = 0; i < MAX; i++) { 
    indexFromEnd = (MAX - 1) - i; 
.... 
} 
+1

Я не согласен с этим. Я думаю, что реорганизованный пример yur также затрудняет понимание, потому что я должен остановиться и подумать, что делает ваша строка indexFromEnd. Дескрипцию для цикла трудно понять, поскольку вместо ++ будет непосредственным визуальным ключом. – user15299

+0

Тогда дайте ему лучшее имя. Конкретный контекст недостаточен для этого. Я все еще поддерживаю свою позицию, что для циклов должно быть просто 0..MAX-1 –

+0

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

-2

Если у вас есть список использовать ListIterator:

Следуя примеру на основе http://www.java-samples.com/showtutorial.php?tutorialid=235

class ListIter { 
    public static void main(String args[]) { 
     // create an array list 
     ArrayList al = new ArrayList(); 
     // add elements to the array list 
     al.add("A"); 
     al.add("B"); 
     al.add("C"); 
     al.add("D"); 
     al.add("E"); 
     al.add("F"); 
     // use ListIterator to display contents of al backwards 
     ListIterator litr = al.listIterator(al.size()); 
     while (litr.hasPrevious()) { 

      Object element = litr.previous(); 
      System.out.print(element + " "); 

     } 
     System.out.println(); 
    } 
} 
0

Мой голос для:

для (int id х = (LEN-1); IDX> = 0; idx--)

И как в сторону, я одобряю оператору префиксом инкремента/декремента (--idx) в течение по-петлями, так как он будет избегать ненужной копии IDX (хотя многие компиляторы, вероятно, узнайте это и исправьте его для вас).

+0

'for (int idx = len; -idx> = 0;)' является более кратким. FWIW, пред-декрементная форма '--idx> = 0' требует меньше кодов байтов Java, чем пост-декрементная форма' idx--> 0'. –

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