цикл foreach примитивом или классом в штучной упаковке в Java

1

В настоящее время я читаю книгу "Java Generics and Collections", и я нашел интересный код:

List<Integer> ints = Arrays.asList(1,2,3);
int s = 0;
for (int n : ints) { s += n; }
assert s == 6;

Здесь foreach цикл итерации по примитивам:

for (int n : ints) { ... }

Тем не менее, Eclipse IDE предлагает мне перебирать по бокс-типу:

for (Integer n : ints) { ... }

Существуют ли какие-либо преимущества использования того или иного стиля итерации?

  • 0
    коллекция не поддерживает примитивные типы, поэтому есть класс-оболочка для использования примитивов в коллекциях.
  • 0
    генерики удаляются во время выполнения, поэтому ваш список заполняется объектами. При получении они возвращаются к Integer . Когда вы перебираете список со значениями int , вы заставляете распаковку делать для каждой итерации.
Теги:
generics
collections
unboxing
boxing

2 ответа

5
Лучший ответ

Бокс/распаковка имеет стоимость во время выполнения.

  • если вы собираетесь распаковать Integer один раз внутри тела вашего цикла, как и вы, это не будет иметь большого значения.
  • если вы много раз удаляете Integer в тело вашего цикла, вам было бы лучше разобрать его один раз с помощью for(int i: ints)
  • если вы собираетесь использовать Integer в теле вашего цикла, то использование int приведет к ненужной операции unbox/box.

Например:

List<Integer> subList = new ArrayList<>();

for (Integer i : ints) { //better not to unbox
  if (someCondition(i)) subList.add(i);
}

for (int i : ints) { //better to unbox once
  int a = i;
  int b = 2 * i;
  sum += a + b - i;
}
  • 1
    и если вы используете int вместо Integer то это также приведет к более быстрому выполнению, если коллекция имеет огромный размер.
  • 0
    Ваш ответ полезен, однако что, если в цикле есть много мест, где «Integer i» будет распаковано (например, сумма вычисляется вместе с другими арифметическими операциями)? Не лучше ли использовать для (int n: ints)?
Показать ещё 4 комментария
1

Да.

    List<Integer> ints = Arrays.asList(1,2,3); //here lists is of type Integer which is boxed type
    int s = 0; //s is primitive type

Помните, мы можем сравнить только:

1.) примитив к примитивному типу

2.) В штучной упаковке в коробке

мы можем сказать

Список ints может быть представлен как:

    [Integer.valueof(1), Integer.valueof(2), Integer.valueof(3)]

Итак, в следующем коде

    for (int n : ints) // in every loop ints current index value which is an Integer is unboxed and assigned to 'int n'

и когда читается следующий код.

     s += n;// int n is added to int s (primitive added to primitive ie; no conversion done here)

2.) Теперь второй подход

    for (Integer n : ints) { ... }// here, since 'n' is also boxed so no conversion takes place

Однако, когда встречается следующая строка

    s += n; // boxed Integer n is unboxed to a primitive and added to primitive 's' (so unboxing/conversion happens in each addition)

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню