Лучшая идиома для убывающего цикла - PullRequest
4 голосов
/ 02 декабря 2009

Каков наилучший / предпочтительный способ уменьшения цикла for и почему?

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

или

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

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

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

Вероятность того, что тот или иной разработчик может сбить с толку другого разработчика?

Ответы [ 9 ]

11 голосов
/ 02 декабря 2009

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

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

Это предложение от Java Performance Tuning от Jack Shirazi

11 голосов
/ 02 декабря 2009

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

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

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

  • 0 (возможно) более читабельно, чем -1.
  • Сравнение с нулем обычно быстрее, чем сравнение с другими константами. Это отдельная инструкция, которая проверяет одно значение в стеке. Другие сравнения используют одну инструкцию для помещения константы в стек, а другую - для сравнения двух верхних значений.
1 голос
/ 02 декабря 2009

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

1 голос
/ 02 декабря 2009

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

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

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

0 голосов
/ 06 декабря 2009

Мой голос за:

для (int idx = (len-1); idx> = 0; idx -)

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

0 голосов
/ 02 декабря 2009

Если у вас есть список, используйте 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 голосов
/ 02 декабря 2009

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

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

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

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

for(int i = 0; i < MAX; i++) {
  indexFromEnd = (MAX - 1) - i;
....
 }
0 голосов
/ 02 декабря 2009

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

Лично я бы сделал, как писал Марк Байерс .

0 голосов
/ 02 декабря 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...