Java для вопроса производительности цикла - PullRequest
20 голосов
/ 05 марта 2010

с учетом этого примера:

public static void main(final String[] args) {
    final List<String> myList = Arrays.asList("A", "B", "C", "D");
    final long start = System.currentTimeMillis();
    for (int i = 1000000; i > myList.size(); i--) {
        System.out.println("Hello");
    }
    final long stop = System.currentTimeMillis();
    System.out.println("Finish: " + (stop - start));
}

против

public static void main(final String[] args) {
    final List<String> myList = Arrays.asList("A", "B", "C", "D");
    final long start = System.currentTimeMillis();
    final int size = myList.size();
    for (int i = 1000000; i > size; i--) {
        System.out.println("Hello");
    }
    final long stop = System.currentTimeMillis();
    System.out.println("Finish: " + (stop - start));
}

Будет ли это чем-то отличаться? На моей машине второй, кажется, работает быстрее, но я не знаю, насколько он точен. Будет ли компилятор оптимизировать этот код? Я мог бы подумать, что он будет, если условие цикла является неизменным объектом (например, массив строк).

Ответы [ 13 ]

0 голосов
/ 05 марта 2010

Как всегда с такими вещами, вам придется запустить их оба, чтобы увидеть, что быстрее, учитывая реализацию, которую вы используете. Тем не менее, первое имеет потенциальное снижение производительности из-за необходимости вызывать size () каждую итерацию, и вызов функции обходится дороже, чем простая проверка переменной напрямую. Однако возможно, что этот вызов функции может быть оптимизирован в зависимости от вашего кода и того, что делает компилятор, поэтому вам придется запускать тесты, чтобы увидеть.

Однако, как указывал Pindatjuh, лучше использовать цикл foreach, когда вы собираетесь перебирать всю коллекцию таким образом. Это должно позволить компилятору оптимизировать вещи лучше и менее подвержено ошибкам.

0 голосов
/ 05 марта 2010

Разница в одном вызове метода для каждой итерации, поэтому вторая версия должна работать немного быстрее. Хотя, если вы используете компилятор Just-In-Time, он может оптимизировать это - выяснить, что он не изменяется во время цикла. Стандартная реализация Java поддерживает JIT, но не каждая реализация Java делает.

0 голосов
/ 05 марта 2010

В случае «оптимизации компилятора» лучшее, что вы можете сделать, это цикл for-each:

for(final String x : myList) { ... }

Что позволяет компилятору обеспечить самую быструю реализацию.

Edit:

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

Также: «Преждевременная оптимизация - корень всего зла». Печально известный закон Дональда Кнута.

...