2015-03-03 1 views
0

Я новичок Java-ученик. Я пытаюсь понять, как писать эффективные коды с точки зрения производительности и удобочитаемости. На данный момент массивы для меня были загадкой. Ниже приведены шесть примитивных тестов. Первые три и три три возвращаются почти в одно и то же время. Пожалуйста, объясните, что происходит.Какая из них быстрее в производительности цикла петли?

String s= ""; 
int[] Array1=new int[100000]; 
Long startingTime=System.nanoTime(); 
for (int i = 0; i < Array1.length; i++) { 
    s+=i; 
} 
System.out.println("time : " + (System.nanoTime()-startingTime)); 

String s= ""; 
int length=100000; 
Long startingTime=System.nanoTime(); 
for (int i = 0; i < length; i++) { 
    s+=i; 
} 
System.out.println("time : " + (System.nanoTime()-startingTime)); 

String s= ""; 
int length1=50000; 
int length2=50000; 
Long startingTime=System.nanoTime(); 
for (int i = 0; i < length1+length2; i++) { 
    s+=i; 
} 
System.out.println("time : " + (System.nanoTime()-startingTime)); 

public class Test3Length { 
static class Foo { 
int mSplat = 0; 
} 
public static void main(String[] args) { 
int twentyMillions = 20000000; 
Foo[] mArray = new Foo[twentyMillions]; 
for (int i = 0; i < mArray.length; i++) { 
    mArray[i] = new Foo(); 
} 
int sum = 0; 
Long startingTime = System.nanoTime(); 
for (int i = 0; i < mArray.length; ++i) { 
    sum += mArray[i].mSplat; 
} 
System.out.println("time : " + (System.nanoTime() - startingTime)); 
} 
} 

public class Test4Length { 
static class Foo { 
int mSplat = 0; 
} 
public static void main(String[] args) { 
int twentyMillions = 20000000; 
Foo[] mArray = new Foo[twentyMillions]; 
for (int i = 0; i < mArray.length; i++) { 
    mArray[i] = new Foo(); 
} 
int sum = 0; 
Long startingTime = System.nanoTime(); 
for (int i = 0; i < twentyMillions; ++i) { 
    sum += mArray[i].mSplat; 
} 
System.out.println("time : " + (System.nanoTime() - startingTime)); 
} 
} 

public class Test5Length { 
static class Foo { 
int mSplat = 0; 
} 
public static void main(String[] args) { 
int twentyMillions = 20000000; 
Foo[] mArray = new Foo[twentyMillions]; 
for (int i = 0; i < mArray.length; i++) { 
    mArray[i] = new Foo(); 
} 
int sum = 0; 
Long startingTime = System.nanoTime(); 
for (Foo a : mArray) { 
    sum += a.mSplat; 
} 
System.out.println("time : " + (System.nanoTime() - startingTime)); 
} 
} 

Первый вопрос, предпочитаю ли я int length в условиях отсутствия контура, а не array.length?

Второй вопрос, предпочитаю ли я цикл foreach, а не цикл for, если массив не является коллекцией?

+3

Беспокойство относительно удобочитаемости, а не эффективности; [Преждевременная оптимизация - корень всего зла] (http://c2.com/cgi/wiki?PrematureOptimization). – azurefrog

+1

@azurefrog: Как вы знаете, что эта оптимизация преждевременна? Возможно, это код, который OP правильно профилирован и идентифицирован как бутылочная шее. Бывают моменты, когда важна производительность, и научиться ее выводить, безусловно, важно. – Dolda2000

+0

@ Dolda2000 Поскольку вопрос OP начинается с '' я новичок Java-ученика. '', Я предположил, что это не так. – azurefrog

ответ

3

В реальной жизни это не имеет значения, если вы используете foreach или for loop. Разница в производительности едва заметна. Если вам нужен текущий индекс, тогда сделайте для цикла, если нет, то перейдите к foreach. Что касается длины, это просто свойство, и поскольку это массив, он устанавливается, когда массив инициализируется и никогда не изменяется. Чтение значения свойства почти не требует времени. Таким образом, ради читаемость поставим его внутрь для условия цикла в

1

Первый вопрос, я бы предпочел, чтобы int length в обмен на петле состояния, а не array.length?

Это буквально не имеет значения. array.length является инвариантом, поэтому JIT будет получать доступ к нему один раз в любом случае, делая его значение идентичным локальной переменной с точки зрения производительности.

Второй вопрос, мог бы я предпочесть цикл foreach, а не for-loop, если массив не является коллекцией?

Когда объект, который вы зацикливаете, представляет собой массив, перевод цикла foreach такой же, как и для цикла, поэтому это не имеет никакого значения.

Однако в заключение я должен сказать, что вы, кажется, фокусируетесь на неправильных вещах. В первых трех тестах практически все время выполнения, скорее всего, будет потрачено на выражение s+=i, так как каждая оценка создает новый String, чтобы добавить к нему i. Вероятно, вы увидите гораздо более мощные ускорения, используя StringBuilder вместо того, чтобы пытаться использовать разные варианты конструкции цикла.

+0

Спасибо за ответ и комментарии. Вы правы, s + = i использование очень плохой практики. Но я намеренно использовал его в своем примитивном тесте только на более длительное время. Можете ли вы рассказать мне о проблемах с производительностью? Еще раз спасибо. @ Dolda2000. –

+1

@PhotonPoint: Конечно, но это все равно означает, что любой цикл, который вы используете, будет потреблять минимальное количество '' 'полного времени выполнения, поэтому даже тогда это плохой способ проверить разные циклы. – Dolda2000

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