如何改变java中的ArrayList元素的值

请帮助我下面的代码,即使更改值后,我得到相同的输出

import java.util.*; class Test { public static void main(String[] args) { ArrayList<Integer> a = new ArrayList<Integer>(); // added 0-9 to ArrayList for(int i=0;i<9;i++) a.add(new Integer(i)); // initialize the Iterator Iterator<Integer> i = a.iterator(); // changed the value of first element in List if(i.hasNext()) { Integer x = i.next(); x = Integer.valueOf(9); } // initialized the iterator again and print all the elements i = a.iterator(); while(i.hasNext()) System.out.print(i.next()); } } //Output : 012345678 

值9不更新。

该列表维护对存储在列表中的原始值的对象引用。 所以当你执行这一行时:

 Integer x = i.next(); 

x和列表都存储对同一个对象的引用。 但是,执行时:

 x = Integer.valueOf(9); 

列表中没有任何改变,但是x现在存储对不同对象的引用。 名单没有改变。 你需要使用一些列表操作方法,比如

 list.set(index, Integer.valueof(9)) 

注意:这与Integer的不变性没有任何关系,正如其他人所暗示的那样。 这只是基本的Java对象引用行为。


这是一个完整的例子,以帮助解释这一点。 请注意,这使用了ListIterator类,它支持在迭代中移除/设置项目:

 import java.util.*; public class ListExample { public static void main(String[] args) { List<Foo> fooList = new ArrayList<Foo>(); for (int i = 0; i < 9; i++) fooList.add(new Foo(i, i)); // Standard iterator sufficient for altering elements Iterator<Foo> iterator = fooList.iterator(); if (iterator.hasNext()) { Foo foo = iterator.next(); foo.x = 99; foo.y = 42; } printList(fooList); // List iterator needed for replacing elements ListIterator<Foo> listIterator = fooList.listIterator(); if (listIterator.hasNext()) { // Need to call next, before set. listIterator.next(); // Replace item returned from next() listIterator.set(new Foo(99,99)); } printList(fooList); } private static void printList(List<?> list) { Iterator<?> iterator = list.iterator(); while (iterator.hasNext()) { System.out.print(iterator.next()); } System.out.println(); } private static class Foo { int x; int y; Foo(int x, int y) { this.x = x; this.y = y; } @Override public String toString() { return String.format("[%d, %d]", x, y); } } } 

这将打印:

 [99, 42][1, 1][2, 2][3, 3][4, 4][5, 5][6, 6][7, 7][8, 8] [99, 99][1, 1][2, 2][3, 3][4, 4][5, 5][6, 6][7, 7][8, 8] 

你说你在哪里改变第一个元素的价值;

 x = Integer.valueOf(9); 

你正在改变x指向一个全新的Integer,但从不再次使用它。 你不以任何方式改变collections。

既然你正在使用ArrayList,如果你想要一个允许你改变元素的迭代器,你可以使用ListIterator,这是你需要改变代码的代码片段。

//初始化Iterator
ListIterator <Integer> i = a。 listIterator() ;

//更改List中第一个元素的值
if(i.hasNext()){
i.next();
i.set(Integer.valueOf(9)); //更改迭代器当前所在的元素
}

/ /新的迭代器,并打印所有的元素
Iterator iter = a.iterator();
而(iter.hasNext())
是System.out.print(iter.next());

>> 912345678

可悲的是,同样不能扩展到Set <T>等其他集合。 实现细节(例如HashSet被实现为一个哈希表并且改变对象可以改变哈希值并因此改变迭代顺序)使得Set <T>成为“添加新/仅移除”types的数据结构,并且改变内容在迭代过程中一点也不安全。

使用set方法replace旧值。

 list.set( 2, "New" ); 

你正试图改变列表中的值,但是你所做的只是改变x的引用。 做下面的事情只会改变x,而不是集合中的任何东西:

 x = Integer.valueOf(9); 

另外, Integer是不可变的,这意味着你不能改变Integer对象内部的值(这将需要一个不同的方法来完成)。 这意味着你需要replace整个对象。 没有办法用Iterator来做到这一点(没有添加你自己的拳击层)。 做相反的事情:

 a.set(0, 9); 

我同意邓肯…我已经尝试了与可变对象,但仍然得到同样的问题…我有一个简单的解决scheme…使用ListIterator而不是迭代器和使用ListIterator的set方法

 ListIterator<Integer> i = a.listIterator(); //changed the value of first element in List Integer x =null; if(i.hasNext()) { x = i.next(); x = Integer.valueOf(9); } //set method sets the recent iterated element in ArrayList i.set(x); //initialized the iterator again and print all the elements i = a.listIterator(); while(i.hasNext()) System.out.print(i.next()); 

但是,这限制了我只使用ArrayList只能使用ListIterator …我将有任何其他集合相同的问题

我认为问题在于你认为这个说法…

 x = Integer.valueOf(9); 

…导致“9”的值被“存储”到(!)x所引用的对象中。

但那是错的。

相反,声明会导致类似的情况,就好像你会打电话一样

 x = new Integer(9); 

如果你看看java源代码,你会看到详细信息。

以下是“Integer”类中的“valueOf(int i)”方法的代码:

 public static Integer valueOf(int i) { assert IntegerCache.high >= 127; if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i); } 

而且,每当IntegerCache类第一次被使用时,下面的脚本被调用:

 static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } 

您会看到,在valueOf方法中使用“new Integer(i)”创build新的Integer对象…或者返回IntegerCache中存储的Integer对象的引用。

在这两种情况下,x都会引用一个新的对象。

这就是为什么当你调用你的列表中的对象引用丢失…

 x = Integer.valueOf(9); 

而不是这样做,结合ListIterator使用…

 i.set(Integer.valueOf(9)); 

…当你得到你想改变的元素…

 i.next(); 

将其更改for(int i=0;i<=9;i++)