Java для - каждый на методе считывания

Если javac делают то, что я думаю, следующие строки привели бы к той же производительности:

for (Object o: getObjects()) {}
List<Object> os = getObjects(); for (Object o: os) {}

Это так или нет? Или это является, возможно, определенным для реализации? Раз так: кто-либо знает о GWT?

5
задан Jonas Byström 4 June 2010 в 12:13
поделиться

5 ответов

Все эти ответы кажутся правильными с точки зрения чистой Java. Более того, если это возможно, компилятор GWT фактически перепишет расширенный цикл for дальше в обычный цикл for, прежде чем он сгенерирует JavaScript. Так что на самом деле это будет выглядеть примерно так:

for (int i = 0; i < getObjects().size(); i++) {
  Object o = getObjects().get(i);
  // ...
}

Причина? Если объект List итератора никогда не упоминается, он может быть объявлен как мертвый код и не будет переписан в JavaScript, что приведет к уменьшению размера загрузки. Эта оптимизация никак не должна влиять на фактическое выполнение вашего кода.

См. Оптимизация приложений с помощью компилятора GWT из Google I / O в этом году, чтобы узнать больше о других безумных вещах, которые компилятор GWT делает для уменьшения размера JS.

5
ответ дан 18 December 2019 в 06:34
поделиться

Производительность будет идентичной.

Компилятор Java превращает циклы for-each в цикл вокруг объекта Iterator , вызывая метод iterator () для объекта, который вы перебираете.
Следовательно, фактический экземпляр списка используется только один раз. (Для вызова итератора () )

7
ответ дан 18 December 2019 в 06:34
поделиться

Нет никакой разницы. Конструкция foreach просто извлекает из объекта Iterator . Вот почему он должен реализовать интерфейс Iterable .

2
ответ дан 18 December 2019 в 06:34
поделиться

С практической точки зрения вы можете проверить оба байт-кода и сравнить их:

 m1()V
   L0
    ALOAD 0
    INVOKEVIRTUAL it/funge/Console.getObjects()Ljava/util/List;
    INVOKEINTERFACE java/util/List.iterator()Ljava/util/Iterator;
    ASTORE 2
    GOTO L1
   L2
   FRAME FULL [it/funge/Console T java/util/Iterator] []
    ALOAD 2
    INVOKEINTERFACE java/util/Iterator.next()Ljava/lang/Object;
    ASTORE 1
   L1
   FRAME SAME
    ALOAD 2
    INVOKEINTERFACE java/util/Iterator.hasNext()Z
    IFNE L2
   L3
    RETURN

m2()V
   L0
    ALOAD 0
    INVOKEVIRTUAL it/funge/Console.getObjects()Ljava/util/List;
    ASTORE 1
   L1
    ALOAD 1
    INVOKEINTERFACE java/util/List.iterator()Ljava/util/Iterator;
    ASTORE 3
    GOTO L2
   L3
   FRAME FULL [it/funge/Console java/util/List T java/util/Iterator] []
    ALOAD 3
    INVOKEINTERFACE java/util/Iterator.next()Ljava/lang/Object;
    ASTORE 2
   L2
   FRAME SAME
    ALOAD 3
    INVOKEINTERFACE java/util/Iterator.hasNext()Z
    IFNE L3
   L4
    RETURN

Они равны, с той лишь разницей, что ваш второй фрагмент состоит из двух отдельных частей для загрузки Перечислите , а затем получите итератор. Это также потребует больше локальных переменных класса, фактически у него также есть ALOAD и еще ASTORE , он используется для хранения результата getObjects в двух строках кода, а в первом фрагменте он напрямую использует его ..

3
ответ дан 18 December 2019 в 06:34
поделиться

Из спецификаций языка Java:

14.14.2 Расширенный оператор for

Расширенный оператор for имеет форма:

 EnhancedForStatement:
for (Идентификатор типа VariableModifiersopt: выражение)

Выражение должно иметь тип Итерируемый , иначе он должен иметь тип массива (§10.1) или время компиляции возникает ошибка.

Объем объявленной локальной переменной в части FormalParameter расширенный для утверждения (§14.14) Содержимое Заявление

Значение расширенного для заявление дается переводом на основной оператор для .

Если тип Выражение является подтип Iterable , тогда пусть I будет тип выражения Выражение. итератор () . Расширенный оператор для эквивалентен к основному для утверждению форма:

 for (I #i = Expression.iterator (); # i.hasNext ();) {

Идентификатор типа VariableModifiersopt = # i.next ();
Заявление
}

Где #i - созданный компилятором идентификатор, отличный от любого другие идентификаторы (сгенерированные компилятором или иначе), которые входят в сферу действия (§6.3) в точке, где усилено для заявление происходит.

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

7
ответ дан 18 December 2019 в 06:34
поделиться
Другие вопросы по тегам:

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