Существуют некоторые экранные демонстрации на http://showmedo.com
Я думаю, что лучшим подходом может быть использование цикла for.
ArrayList<String> arr = new ArrayList<String>();
for (int i = 0; i < arr.size(); i++) {
String t = arr.get(i);
if (// your condition is met) {
arr.set(i, "your new value");
}
}
For-each не дает вам указателя индекса, поэтому вы просто не можете использовать его для изменения неизменяемого значения.
Либо используйте цикл for с индексом, либо используйте изменяемый тип (например, StringBuffer, а не String)
Проблема в том, что вы пытаетесь изменить ссылку с областью действия цикла t
, чтобы он указывал на новый экземпляр String. Это не сработает. Это не относится к фактической записи в arraylist. Вам необходимо изменить фактическое значение ссылки. Если String
был изменяемым и предоставлял для этого фиктивный метод set ()
, вы могли бы теоретически сделать
for (String t : arr) {
t.set("some other value");
}
или около того, но это невозможно, поскольку он неизменяем. Лучше получить дескриптор точки входа в самом массиве, используя обычный цикл for
:
Массив объектов (например, строк) в Java - это непрерывный блок, содержащий упорядоченную серию ссылок. Итак, когда у вас есть массив из 4 строк, на самом деле у вас есть 4 ссылки, хранящиеся в массиве, и 4 строковых объекта, которые находятся за пределами массива, но на которые ссылаются его 4 элемента.
Какая конструкция for-each в Java это создает локальную переменную и для каждой итерации копирует в эту локальную переменную ссылку из ячейки массива, которая соответствует этой итерации. Когда вы устанавливаете переменную цикла ( t = «какое-то другое значение»
), вы помещаете ссылку на новую строку, «какое-то другое значение»
в локальную переменную t, а не в массив.
Ваш код переписывается компилятором примерно так:
ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)
for (final Iterator <String> i = arr.iterator(); i.hasNext();) {
String t;
t = i.next();
t = " some other value "; // just changes where t is pointing
}
Чтобы делать то, что вы хотите, вам нужно написать цикл for следующим образом:
for (final ListIterator<String> i = arr.iterator(); i.hasNext();) {
final String t;
t = i.next();
i.set("some other value");
}
Итератор не имеет метод set выполняет только ListIterator.
В основном вы хотите удалить String t из списка arr. Просто сделайте arr.remove (t), и все будет готово. Но вы не можете сделать это, просматривая один и тот же список. Вы получите исключение, если попытаетесь изменить список таким образом.
У вас есть два варианта:
Вариант 1 - самый простой, клон можно сделать так:
List<String> clone = new ArrayList<String>(arr);
Вы, кажется, неправильно понимаете, как объекты / ссылки работают в Java, что очень важно для эффективного использования языка. Однако этот код здесь должен делать то, что вы хотите (извините за отсутствие объяснения):
ArrayList<String> arr = new ArrayList<String>();
//... fill with some values (doesn't really matter)
for(int i = 0; i < arr.size(); i++)
{
arr.set(i, " some other value "); // change the contents of the array
}
for(String t : arr)
{
System.out.println(t);
}
Я считаю, что это не связано с неизменяемыми или изменяемыми.
t = " some other value "; //hoping this would change the actual array
t не содержит ссылки на реальный объект. Java копирует значение из arrayylist и помещает это значение в t, поэтому значение списка массивов не влияет.
HTH
На этот вопрос дан хороший ответ. Тем не менее, вот мое предложение. Внутренний цикл var t виден только там. Его не будет видно вне цикла. Вы могли бы выполнить t.set ()
, если бы это была не String
.
Строки неизменяемы. Если у вас есть изменяемый тип, например StringBuilder / Buffer, вы можете изменить строку в своей итерации. Помните, у вас есть ссылки.
Используйте StringBuffer
, а не простые строки. Таким образом, строка внутри может изменяться.