ArrayList的问题(迭代的时候不允许修改)

下面是我今天回答帖子中最尴尬的一个,

问题:请直接看下面第一段代码的注释处
下面两段代码主要是说明通过内部类来实现,多重继承的功能,通过内部类来继承Event类,然后外部类继承Controller类,将继承了Event的内部类对象放到eventList中,来调用。

Java code
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->package controller; import java.util.*; public class Controller { private List<Event> eventList = new ArrayList<Event>(); public void addEvent(Event c){ eventList.add(c); } public void run(){ while(eventList.size() > 0){ //for(Event e : eventList){ //如果是直接用,则会出错。 for(Event e : new ArrayList<Event>(eventList)){ //为什么这里要再新建一个new ArrayList<Event>(eventList)? if(e.ready()){ System.out.println(e); e.action(); eventList.remove(e); } } } } }

Java code
<!-- Code highlighting produced by Actipro CodeHighlighter (freeware) http://www.CodeHighlighter.com/ -->package controller; public abstract class Event { private long eventTime; protected final long delayTime; public Event(long delayTime){ this.delayTime = delayTime; } public void start(){ eventTime = System.nanoTime() + delayTime; } public boolean ready(){ return System.nanoTime() >= eventTime; } public abstract void action(); }
我一直以为:
//for(Event e : eventList){ //如果是直接用,则会出错。 
for(Event e : new ArrayList <Event>(eventList)){
//为什么这里要再新建一个new ArrayList <Event>(eventList)?

为什么会出现这样的错误呢,其实原因是楼主没有理解透for循环中创建的均为临时变量,
如:这里在for 循环中Event e,其实是创建的临时对象,它的生命周期只是在这个for循环之内,
当for循环结束时,就会自动销毁了,所以需要建立一个new ArrayList <Event>(eventList)临时对象来实现循环,
不然就会出现上述情况。
后来企鹅老兄说:ArrayList的问题,迭代的时候不允许修改. 结贴.
我太自卑了,呵呵,现在会了,以后就知道了!
<think>嗯,用户问的是如何在Java中使用迭代器在迭代过程中修改ArrayList对象的排序属性。首先,我需要回忆一下JavaArrayList和迭代器的相关知识。 记得ArrayList是线程安全的,如果在迭代过程中修改结构,比如添加或删除元素,会抛出ConcurrentModificationException。但用户的问题是关于修改元素的属性,而是结构变化。这时候可能需要确认是否允许这样的操作。 根据引用[3],迭代器允许历时通过remove方法删除元素,但其他修改可能有限制。用户想修改用于排序的属性,比如对象的某个字段,这样会影响后续的排序结果。这时候直接修改对象的属性应该是允许的,因为会改变ArrayList的结构。例如,如果有一个Person对象的ArrayList修改其age字段,会导致结构变化,所以会触发异常。 过,如果在迭代过程中修改了属性,之后需要重新排序,可能需要调用sort方法。引用[1]提到可以用ArrayList的sort方法进行排序,可以传入自定义的Comparator。例如,修改属性后,调用sort方法重新排序列表。 需要注意的是,如果在迭代过程中使用list的add或remove等方法,会导致ConcurrentModificationException,但修改元素属性本身是允许的。因此,用户的问题的解决方案可能是在迭代时修改属性,然后在迭代结束后调用sort方法重新排序。 另外,引用[2]提到并发包中的类如CopyOnWriteArrayList可以在迭代时修改集合,但用户使用的是ArrayList,所以需要避免结构修改。而修改元素属性属于结构修改,所以是安全的。 最后,用户可能需要一个示例代码来展示如何操作。代码部分需要展示如何用迭代器ArrayList修改对象属性,然后调用sort方法进行重新排序。同时提醒用户要在迭代过程中进行结构修改,并注意线程安全问题。</think>在Java中通过迭代器修改ArrayList对象排序属性时,需注意以下实现方法和限制条件: ### 一、迭代器修改属性的实现方法 1. **通过对象引用直接修改**(适用于非结构变更) ```java Iterator<Person> it = list.iterator(); while(it.hasNext()){ Person p = it.next(); p.setAge(25); // 直接修改对象的排序关键属性 } Collections.sort(list, Comparator.comparingInt(Person::getAge)); // 重新排序[^1] ``` 2. **使用ListIterator双向迭代器** ```java ListIterator<Person> lit = list.listIterator(); while(lit.hasNext()){ Person p = lit.next(); p.setSalary(p.getSalary()*1.1); // 修改排序字段 lit.set(p); // 显式更新元素引用[^3] } ``` ### 二、关键限制与注意事项 1. **结构修改限制** - 禁止在迭代期间直接调用`ArrayList.add()/remove()` - 修改对象属性会触发`ConcurrentModificationException` 2. **排序更新要求** - 属性修改后必须显式调用排序方法 - 推荐使用Java 8+的lambda表达式排序: ```java list.sort(Comparator.comparing(Employee::getName, String.CASE_INSENSITIVE_ORDER)); ``` 3. **线程安全方案** ```java List<Person> syncList = Collections.synchronizedList(new ArrayList<>()); // 同步块内操作 synchronized(syncList) { Iterator<Person> it = syncList.iterator(); while(it.hasNext()) { it.next().updateSortKey(); } Collections.sort(syncList); } ``` ### 三、替代方案对比 | 方案 | 优点 | 缺点 | |--------------------|---------------------|----------------------| | 直接修改+重新排序 | 实现简单 | 需要完整重新排序 | | CopyOnWriteArrayList | 避免并发修改异常[^2] | 内存消耗大,适合读多写少场景 | | Stream API | 函数式编程,代码简洁 | 需要Java 8+支持 |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值