Почему цикл for-each не позволяет увеличивать Integer? - PullRequest
1 голос
/ 09 февраля 2011

Я имею в виду в этом коде:

List<Integer> list = new LinkedList();
list.add(1);
list.add(2);
list.add(3);

for (Integer i : list)
    i++;

System.out.println(list.get(0))

возвращает 1, а не 2. В цикле for-each Java создает новый объект (i) и копирует значение поля из объекта в List?

Ответы [ 6 ]

9 голосов
/ 09 февраля 2011

оператор ++ не является допустимым оператором для объекта Integer, поэтому Java использует свои функции автобокса для преобразования объекта Integer в примитив int.Как только он преобразован, примитив int увеличивается.Вы не сохраняете примитив, поэтому он теряется.

Для достижения цели вам нужно сделать что-то вроде

List<Integer> list = new LinkedList();
list.add(1);
list.add(2);
list.add(3);


for (int index; index < list.size(); index++) {
   int value = list.get(index).intValue();
   value++;
   list.set(index, Integer.valueOf(value));
}

System.out.println(list.get(0))

Код выше не является оптимальным;но он не использует автобокс.Оптимизированное решение будет использовать ListIterator (добавленный по многочисленным просьбам): ^)

ListIterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
  iterator.set(iterator.get()++);
}

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

ListIterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
  iterator.set(Integer.valueOf(iterator.get().intValue()++));
}
8 голосов
/ 09 февраля 2011

Integer s являются неизменяемыми.

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

Оригинал Integer Экземпляр в списке не изменен (и не может быть изменен).

7 голосов
/ 09 февраля 2011

Это позволяет, не делает то, что вы думаете.

То, что у вас есть сокращение для.

for (Iterator<Integer> iter = list.iterator(); iter.hashNext();) {
    Integer i = iter.next();
    i++; // value is discarded after this line.
}

РЕДАКТИРОВАТЬ: вместо использования get (i) и set (i, value), которые могут быть очень дорогими для LinkedList, лучшим выбором будет использование ListIterator.

for (ListIterator<Integer> iter = list.listIterator(); iter.hasNext();)
    iter.set(iter.next()+1);
0 голосов
/ 09 февраля 2011

Поскольку все ответы касаются неизменности, вот как это будет выглядеть с изменяемым типом:

import java.util.concurrent.AtomicInteger;


List<AtomicInteger> list = new LinkedList<AtomicInteger>();
list.add(new AtomicInteger(1));
list.add(new AtomicInteger(2));
list.add(new AtomicInteger(3));

for (AtomicInteger i : list)
    i.getAndIncrement();

System.out.println(list.get(0));

Это должно вывести 2.(AtomicInteger дополнительно имеет эти свойства безопасности потока, но здесь нам нужна только изменчивость.)

Тип примитива int (как и все примитивы) также является неизменяемым, поэтому следующий вариант все равно будет выводить 1:

int[] list = new int[]{ 1, 2, 3};

for (int i : list)
    i++;

System.out.println(list[0]);
0 голосов
/ 09 февраля 2011

Потому что Integer является неизменным, как String и т. Д.

Оператор ++ для целого числа аналогичен операции:

i = new Integer(i.intValue()+1);`

Вам потребуется list.set(index, i);, чтобы изменить значение в вашем списке.

for (int index=0; index<list.size(); index++) {
   list.set(index, list.get(index)+1);
}
0 голосов
/ 09 февраля 2011

Поскольку 0-й элемент в списке - это «1», который вы добавили в строку 2.

О, я понимаю: вы хотите увеличить целые числа.Вы должны сделать:

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

Обратите внимание, что целочисленные экземпляры являются неизменяемыми.Значение не может измениться!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...