Самый быстрый способ выполнить итерации Массива в Java: переменная цикла по сравнению с расширенным для оператора [дубликат]

Откройте package.json и начните удалять пакеты по одному, пока предупреждение не исчезнет.

enter image description here

После удаления "webpack": "^1.12.14", из package.json я больше не получаю предупреждение

enter image description here

28
задан Ciro Santilli 新疆改造中心法轮功六四事件 7 May 2015 в 13:45
поделиться

5 ответов

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

Например, рассмотрите следующий код:

public static void main(String[] args)
{
    for (String x : args)
    {
        System.out.println(x);
    }
}

При декомпиляции с javap -c Test мы получаем (для метода main ):

public static void main(java.lang.String[]);
  Code:
   0:   aload_0
   1:   astore_1
   2:   aload_1
   3:   arraylength
   4:   istore_2
   5:   iconst_0
   6:   istore_3
   7:   iload_3
   8:   iload_2
   9:   if_icmpge   31
   12:  aload_1
   13:  iload_3
   14:  aaload
   15:  astore  4
   17:  getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:  aload   4
   22:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   25:  iinc    3, 1
   28:  goto    7
   31:  return

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

public static void main(String[] args)
{
    for (int i = 0; i < args.length; i++)
    {
        System.out.println(args[i]);
    }
}

Это декомпилируется в:

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iload_1
   3:   aload_0
   4:   arraylength
   5:   if_icmpge   23
   8:   getstatic   #2; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:  aload_0
   12:  iload_1
   13:  aaload
   14:  invokevirtual   #3; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   17:  iinc    1, 1
   20:  goto    2
   23:  return

Там есть немного больше кода настройки в расширенном цикле for, но в основном они делают то же самое. Итераторы не задействованы. Более того, я бы ожидал, что они будут JIT-ориентированы на еще более похожий код.

Предложение: если вы действительно думаете, что это может иметь существенное значение (что могло бы произойти только когда-либо , если бы тело цикла абсолютно крошечный), то вам следует сравнить его с вашим реальным приложением. Это единственная важная ситуация.

55
ответ дан 28 November 2019 в 02:28
поделиться

Это прямо относится к области микрооптимизации . Это действительно не важно. Стилистически я всегда предпочитаю второй, потому что он более краток, если вам не нужен счетчик циклов для чего-то еще. И это гораздо важнее, чем такая микрооптимизация : читабельность.

При этом, для ArrayList не будет большой разницы, но LinkedList будет намного эффективнее со вторым.

22
ответ дан 28 November 2019 в 02:28
поделиться

Измерьте. Ответ на все вопросы о производительности может зависеть от версии виртуальной машины, процессора, скорости памяти, кешей и т. Д. Таким образом, вы должны измерить это для вашей конкретной платформы.

Лично я предпочел бы второй вариант, потому что намерение больше Чисто. Если производительность станет проблемой, я все равно могу оптимизировать ее позже - если этот код действительно важен для производительности всего приложения.

7
ответ дан 28 November 2019 в 02:28
поделиться

В массиве или коллекции RandomAccess вы можете немного увеличить скорость, выполнив:

List<Object> list = new ArrayList<Object>();

for (int i=0, d=list.size(); i<d; i++) {
    something(list.get(i));
}

Но в целом я бы не стал беспокоиться. Подобные оптимизации не повлияют на ваш код более чем на 0,1%. Попробуйте вызвать java с помощью -prof , чтобы увидеть, на что ваш код на самом деле тратит свое время.

1
ответ дан 28 November 2019 в 02:28
поделиться

Еще быстрее можно использовать ParallelArray инфраструктуры fork-join (если у вас достаточно большой набор данных).

0
ответ дан 28 November 2019 в 02:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: