2009-07-22 6 views
22

Предположим, у меня есть следующий код, есть три для цикла, чтобы что-то сделать. Будет ли он работать быстро, если я изменил самый внешний для цикла цикл while? спасибо ~~Java for loop vs. while loop. Разница в производительности?

int length = 200; 
int test = 0; 
int[] input = new int[10]; 

for(int i = 1; i <= length; i++) { 
    for (int j = 0; j <=length - i; j++) { 
     for (int k = 0; k < length - 1; k++) { 
      test = test + input[j + k]; 
     } 
    } 
} 
+1

Будет оптимизирован до test = 0; потому что массив не заполнен, поэтому test = test + input [j + k]; всегда будет равным нулю. –

+1

Время! также idk java, но я знаю в perl, что стиль C для циклов медленнее, чем при цикле esp в случае чтения файлов. – xenoterracide

ответ

47

Нет, изменение типа петли не имеет значения.

Единственное, что может сделать это быстрее, - это иметь меньше вложенных контуров и зацикливаться на меньших значениях.

Единственным отличием между циклом for и циклом while является синтаксис их определения. Никакой разницы в производительности вообще нет.

int i = 0; 
while (i < 20){ 
    // do stuff 
    i++; 
} 

ли так же, как:

for (int i = 0; i < 20; i++){ 
    // do Stuff 
} 

(на самом деле для цикла немного лучше, потому что i будет из сферы после цикла в то время как i будет придерживаться вокруг в петле while case.)

Цикл for - это просто синтаксически более красивый способ петлирования.

+5

вы можете добавить область вокруг i, чтобы сбить ее с стека после того, как вы закончите с ней: D – Polaris878

+1

За цикл и цикл while на самом деле немного отличаются из-за того, как продолжается поведение. Инкремент всегда будет возникать в цикле for, тогда как продолжение в цикле while пропустит его, в результате чего цикл будет продолжаться вечно. – cleong

+1

Почему это не правильный ответ? ИМХО объясняет, как именно работать с этими циклами. –

1

Нет, вы все еще повторяете то же самое количество раз. Совсем неважно.

0

Было бы важно, если вы используете многопотоковое или многопроцессорное программирование. Тогда это также зависит от того, как вы назначаете петли для различных процессоров/потоков.

1

Посмотрите на свой алгоритм! Знаете ли вы заранее, какие значения из вашего массива добавляются более одного раза?

Если вы знаете, что можете уменьшить количество циклов, и это приведет к повышению производительности.

8

Вы не можете оптимизировать его, изменив его на время.

вы можете просто увеличивать скорость очень очень очень очень мало, изменив линию

for (int k = 0; k < length - 1; k++) { 

по

for (int k = 0; k < lengthMinusOne; k++) { 

где lengthMinusOne вычисляется перед тем

это вычитание просто вычисления почти (200x201/2) x (200-1) раз, и это очень мало для компьютера :)

+5

Компилятор Java будет оптимизировать этот вызов обычно в эти дни. Но вы технически правильны в том, что быстрее. – jjnguy

+2

Хех, я ожидал, что кто-то предложит изменить 'k ++' на '++ k': D –

+0

вы сэкономите очень очень очень мало времени на компиляцию. Большинство компиляторов теперь поддерживают такую ​​оптимизацию. Https://stackoverflow.com/questions/5981460/optimization-by-java-compiler –

25

Такая микро-оптимизация бессмысленна.

  • Контур while не будет быстрее.
  • Структура петли не ваше узкое место.
  • Сначала оптимизируйте свой алгоритм.
  • Еще лучше, сначала не оптимизируйте. Оптимизируйте только после того, как узнаете, что у вас действительно есть узкое место в вашем алгоритме, который не зависит от ввода-вывода.
2

Даже если гипотеза о том, что цикл while был быстрее, чем цикл for, был истинным (а это не так), петли, которые вам пришлось бы изменять/оптимизировать, не были бы внешними, а внутренними, потому что они выполняются больше раз.

2

Разница между ними для и в то время как это семантический:

  • В цикле в то время как вы будете цикл до тех пор, пока условие истинно, которое может меняться много, потому что вы могли бы, в цикле , модифицировать переменные, используя для определения условия while.
  • Обычно в цикле for вы выполняете цикл N раз. Этот N может быть переменным, но не перемещается до конца вашего цикла N, поскольку обычно разработчики не изменяют переменные, оцененные в состоянии цикла.

Это способ помочь другим понять ваш код. Вы не обязаны изменять для переменных цикла, но это обычная (и хорошая) практика.

0

Не было бы разницы в производительности. Попробуйте!

Виртуальная машина Java и, кроме того, компилятор, сделает обе петли в нечто вроде

label: 
     ;code inside your for loop. 
    LOOP label 
2

вот полезный link к статье по этому вопросу

в соответствии с ним, Хотя и для почти в два раза быстрее, но оба они одинаковы.

НО эта статья была написана в 2009 году, и поэтому я попробовал его на моей машине, и вот результаты:

  • с помощью Java 1.7: Итератор было около 20% -30% быстрее, чем для и в то время (которые были все те же)
  • с использованием Java 1.6: Итератор было около 5% быстрее, чем для и While (которые были все те же)

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

+0

На любом безопасном языке использование итератора обычно выполняется быстрее, поскольку интерпретатор/проверка. – cleong

5

Кто-то предложил протестировать петли while против for, поэтому я создал некоторый код для проверки того, были ли ускорены циклы или циклы; в среднем более 100 000 тестов, while цикл был быстрее ~ 95% времени. Возможно, я неправильно его закодировал, но я совсем не привык к кодированию, также учитывая, что, если я запускал всего 10 000 циклов, они оказались довольно даже в режиме запуска.

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

import java.util.Arrays; 

class WhilevsForLoops { 

public static void main(String[] args) { 

final int trials = 100; //change number of trials 
final int trialsrun = trials - 1; 

boolean[] fscount = new boolean[trials]; //faster/slower boolean 
int p = 0; // while counter variable for for/while timers 



while (p <= trialsrun) { 
    long[] forloop = new long[trials]; 
    long[] whileloop = new long[trials]; 

    long systimeaverage; 
    long systimenow = System.nanoTime(); 
    long systimethen = System.nanoTime(); 

    System.out.println("For loop time array : "); 
    for (int counter=0;counter <= trialsrun; counter++) { 
     systimenow = System.nanoTime(); 
     System.out.print(" #" + counter + " @"); 
     systimethen = System.nanoTime(); 
     systimeaverage = (systimethen - systimenow); 
     System.out.print(systimeaverage + "ns |"); 

     forloop[counter] = systimeaverage; 
    } 

    int count = 0; 
    System.out.println(" "); 
    System.out.println("While loop time array: "); 
    while (count <= trialsrun) { 
     systimenow = System.nanoTime(); 
     System.out.print(" #" + count + " @"); 
     systimethen = System.nanoTime(); 
     systimeaverage = (systimethen - systimenow); 
     System.out.print(systimeaverage + "ns |"); 

     whileloop[count] = systimeaverage; 
     count++; 
    } 


    System.out.println("==============================================="); 
    int sum = 0; 

    for (int i = 0; i <= trialsrun; i++) { 
     sum += forloop[i]; 
    } 

    System.out.println("for loop time average: " + (sum/trials) + "ns"); 

    int sum1 = 0; 

    for (int i = 0; i <= trialsrun; i++) { 
     sum1 += whileloop[i]; 
    } 
    System.out.println("while loop time average: " + (sum1/trials) + "ns"); 



    int longer = 0; 
    int shorter = 0; 
    int gap = 0; 

    sum = sum/trials; 
    sum1 = sum1/trials; 

    if (sum1 > sum) { 
     longer = sum1; 
     shorter = sum; 
    } 
    else { 
     longer = sum; 
     shorter = sum1; 
    } 

    String longa; 

    if (sum1 > sum) { 
     longa = "~while loop~"; 
    } 
    else { 
     longa = "~for loop~"; 
    } 

    gap = longer - shorter; 
    System.out.println("The " + longa + " is the slower loop by: " + gap + "ns"); 
    if (sum1 > sum) { 
    fscount[p] = true; } 
    else { 
     fscount[p] = false; 
    } 
    p++; 
} 

    int forloopfc=0; 
    int whileloopfc=0; 

    System.out.println(Arrays.toString(fscount)); 

    for(int k=0; k <= trialsrun; k++) { 
     if (fscount[k] == true) { 
      forloopfc++; } 
      else { 
       whileloopfc++;} 

    } 

    System.out.println("--------------------------------------------------"); 

    System.out.println("The FOR loop was faster: " + forloopfc + " times."); 
    System.out.println("The WHILE loop was faster: " + whileloopfc + " times."); 
} 

} 
0

Кто-нибудь пробовал вот так ...

int i = 20; 
while (--i > -1){ 
    // do stuff 
} 

По сравнению с:

for (int i = 0; i < 20; i++){ 
    // do Stuff 
} 
-2
+0

вывод в вашей ссылке показывает, что механизм Итератора является самым медленным методом для циклического перехода по списку. Между циклами For и While нет большой производительности. –

+0

В статье даже не сказано, что цикл While работает быстрее, чем цикл For. – Englund

0

Исходя из этого: https://jsperf.com/loops-analyze (не создано мной) цикл, а это 22% медленнее, чем цикл for в целом. По крайней мере, в Javascript это так.