要求:对程序做出修改,用LinkedList代替ArrayList,并使用Iterator来循环遍历事件集。原程序比较长下面是关键的部分程序
//: mypackage/Event.java
package mypackage;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime=delayTime;
start();
}
public void start() {
eventTime=System.nanoTime()+delayTime;
}
public boolean ready() {
return System.nanoTime()>=eventTime;
}
public abstract void action();
}//: mypackage/Controller.java
package mypackage;
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:new ArrayList<Event>(eventList))
if(e.ready()) {
e.action();
eventList.remove(e);
}
}
}上面的程序是正确的,运行正常。下面是我修改以后的程序,只改动Controller类里的eventList类型跟run()方法的遍历实现,可是修改后的程序出错了,想了很久想不出原因希望高手能指点一二。。修改后Controller类如下:
public class Controller {
private LinkedList<Event> eventList=new LinkedList<Event>();
Iterator<Event> it=eventList.iterator();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
Event e;
while(eventList.size()>0)
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}
}
}
//Iterator<Event> it=eventList.iterator();到底要放到run()方法里还是方法外我有点
//模糊不过放到run()里一样出错,希望高手能指出问题并给个简明的修改方案,小弟不胜感激!
//: mypackage/Event.java
package mypackage;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime=delayTime;
start();
}
public void start() {
eventTime=System.nanoTime()+delayTime;
}
public boolean ready() {
return System.nanoTime()>=eventTime;
}
public abstract void action();
}//: mypackage/Controller.java
package mypackage;
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:new ArrayList<Event>(eventList))
if(e.ready()) {
e.action();
eventList.remove(e);
}
}
}上面的程序是正确的,运行正常。下面是我修改以后的程序,只改动Controller类里的eventList类型跟run()方法的遍历实现,可是修改后的程序出错了,想了很久想不出原因希望高手能指点一二。。修改后Controller类如下:
public class Controller {
private LinkedList<Event> eventList=new LinkedList<Event>();
Iterator<Event> it=eventList.iterator();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
Event e;
while(eventList.size()>0)
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}
}
}
//Iterator<Event> it=eventList.iterator();到底要放到run()方法里还是方法外我有点
//模糊不过放到run()里一样出错,希望高手能指出问题并给个简明的修改方案,小弟不胜感激!
放到run方法里面,while(eventList.size()>0)这个循环去掉,如果此时其他地方会操作eventList,就需要在迭代的时候锁住它
package mypackage;
import java.util.*;
public class Controller {
private LinkedList<Event> eventList=new LinkedList<Event>();
Iterator<Event> it=eventList.iterator();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
Event e;
while(eventList.size()>0)
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}
}
}//: mypackage/Event.java
package mypackage;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime=delayTime;
start();
}
public void start() {
eventTime=System.nanoTime()+delayTime;
}
public boolean ready() {
return System.nanoTime()>=eventTime;
}
public abstract void action();
}//: mypackage/GrrenhouseControls.java
package mypackage;
public class GreenhouseControls extends Controller {
public class WaterOn extends Event {
public WaterOn(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Greenhouse water is on");
}
}
public class WaterOff extends Event {
public WaterOff(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Greenhouse water is off");
}
}
public class Bell extends Event {
public Bell(long delayTime) {
super(delayTime);
}
public void action() {
addEvent(new Bell(delayTime));
System.out.println("Bint!");
}
}
public class Restart extends Event {
private Event[] eventList;
public Restart(long delayTime,Event[] eventList) {
super(delayTime);
this.eventList=eventList;
for(Event e:eventList)
addEvent(e);
}
public void action() {
for(Event e:eventList) {
e.start();
addEvent(e);
}
start();
addEvent(this);
System.out.println("Restarting system");
}
}
public static class Terminate extends Event {
public Terminate(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Terminating");
System.exit(0);
}
}
}//: main.GreenhouseController.java
package main;
import mypackage.*;
public class GreenhouseController {
public static void main(String[] args) {
GreenhouseControls gc=new GreenhouseControls();
gc.addEvent(gc.new Bell(900));
Event[] eventList={
gc.new WaterOn(600),
gc.new WaterOff(800),
};
gc.addEvent(gc.new Restart(2000,eventList));
if(args.length==1)
gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0])));
gc.run();
System.out.println("end");
}
}如果把Controller类改成题目中讲的正确的代码,程序可以正常运行,不过我换用Iterator来遍历就会报错。。运行后信息如下:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.remove(Unknown Source)
at mypackage.Controller.run(Controller.java:17)
at main.GreenhouseController.main(GreenhouseController.java:15)
Bint!
package mypackage;
import java.util.*;
public class Controller {
private LinkedList<Event> eventList=new LinkedList<Event>();
Iterator<Event> it=eventList.iterator();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
Event e;
while(eventList.size()>0)
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}
}
}//: mypackage/Event.java
package mypackage;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime=delayTime;
start();
}
public void start() {
eventTime=System.nanoTime()+delayTime;
}
public boolean ready() {
return System.nanoTime()>=eventTime;
}
public abstract void action();
}//: mypackage/GrrenhouseControls.java
package mypackage;
public class GreenhouseControls extends Controller {
public class WaterOn extends Event {
public WaterOn(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Greenhouse water is on");
}
}
public class WaterOff extends Event {
public WaterOff(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Greenhouse water is off");
}
}
public class Bell extends Event {
public Bell(long delayTime) {
super(delayTime);
}
public void action() {
addEvent(new Bell(delayTime));
System.out.println("Bint!");
}
}
public class Restart extends Event {
private Event[] eventList;
public Restart(long delayTime,Event[] eventList) {
super(delayTime);
this.eventList=eventList;
for(Event e:eventList)
addEvent(e);
}
public void action() {
for(Event e:eventList) {
e.start();
addEvent(e);
}
start();
addEvent(this);
System.out.println("Restarting system");
}
}
public static class Terminate extends Event {
public Terminate(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Terminating");
System.exit(0);
}
}
}//: main.GreenhouseController.java
package main;
import mypackage.*;
public class GreenhouseController {
public static void main(String[] args) {
GreenhouseControls gc=new GreenhouseControls();
gc.addEvent(gc.new Bell(900));
Event[] eventList={
gc.new WaterOn(600),
gc.new WaterOff(800),
};
gc.addEvent(gc.new Restart(2000,eventList));
if(args.length==1)
gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0])));
gc.run();
System.out.println("end");
}
}如果把Controller类改成题目中讲的正确的代码,程序可以正常运行,不过我换用Iterator来遍历就会报错。。运行后信息如下:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.remove(Unknown Source)
at mypackage.Controller.run(Controller.java:17)
at main.GreenhouseController.main(GreenhouseController.java:15)
Bint!
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 (Iterator<Event> it = eventList.iterator(); it.hasNext();) {
Event e = it.next();
if (e.ready()) {
e.action();
eventList.remove(e);
}
} }
}
}PS:楼主最好把代码写在代码块理
//: mypackage/Controller.java
package mypackage;
import java.util.*;
public class Controller {
private LinkedList<Event> eventList=new LinkedList<Event>();
Iterator<Event> it=eventList.iterator();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() {
Event e;
while(eventList.size()>0)
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}
}
}//: mypackage/Event.java
package mypackage;
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime=delayTime;
start();
}
public void start() {
eventTime=System.nanoTime()+delayTime;
}
public boolean ready() {
return System.nanoTime()>=eventTime;
}
public abstract void action();
}//: mypackage/GrrenhouseControls.java
package mypackage;
public class GreenhouseControls extends Controller {
public class WaterOn extends Event {
public WaterOn(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Greenhouse water is on");
}
}
public class WaterOff extends Event {
public WaterOff(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Greenhouse water is off");
}
}
public class Bell extends Event {
public Bell(long delayTime) {
super(delayTime);
}
public void action() {
addEvent(new Bell(delayTime));
System.out.println("Bint!");
}
}
public class Restart extends Event {
private Event[] eventList;
public Restart(long delayTime,Event[] eventList) {
super(delayTime);
this.eventList=eventList;
for(Event e:eventList)
addEvent(e);
}
public void action() {
for(Event e:eventList) {
e.start();
addEvent(e);
}
start();
addEvent(this);
System.out.println("Restarting system");
}
}
public static class Terminate extends Event {
public Terminate(long delayTime) {
super(delayTime);
}
public void action() {
System.out.println("Terminating");
System.exit(0);
}
}
}//: main.GreenhouseController.java
package main;
import mypackage.*;
public class GreenhouseController {
public static void main(String[] args) {
GreenhouseControls gc=new GreenhouseControls();
gc.addEvent(gc.new Bell(900));
Event[] eventList={
gc.new WaterOn(600),
gc.new WaterOff(800),
};
gc.addEvent(gc.new Restart(2000,eventList));
if(args.length==1)
gc.addEvent(new GreenhouseControls.Terminate(new Integer(args[0])));
gc.run();
System.out.println("end");
}
} 如果把Controller类改成题目中讲的正确的代码,程序可以正常运行,不过我换用Iterator来遍历就会报错。。运行后信息如下:
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedList$ListItr.checkForComodification(Unknown Source)
at java.util.LinkedList$ListItr.remove(Unknown Source)
at mypackage.Controller.run(Controller.java:17)
at main.GreenhouseController.main(GreenhouseController.java:15)
Bint!
初步看了你的代码,问题的根源是在Controller 类中run()代码的此处:
if(e.ready()) {
e.action();//此处可能会向链表中add结点(注意:不是通过it遍历器来add(..)的!)
it.remove();//此处又从链表中删除当前结点
}
显然楼主对究竟怎样正确使用it遍历器还不是很清楚.
现在你的代码已经这样了,如果要以最少代码来修改(不影响程序大的结构),则代码可修改为(保证成功):
将:while(it.hasNext()) {
e=it.next();
if(e.ready()) {
e.action();
it.remove();
}
}改为:
while(it.hasNext()) {
e=it.next();
if(e.ready()) {
it.remove();
int len=eventList.size();
e.action();
if(len!=eventList.size()) it=eventList.iterator();
} //if
} //while
楼主的代码异常主要是由于Iterator的remove方法报的,楼主的集合是想删除一个再增加一个,形成了死循环。不停的删除增加。可以集合链表中的对象的地址是改变了。删除的对象和重新生成的对象的地址是不一样的。迭代器remove的之前,集合链表发生了变化,而迭代器还是指向原来的集合链表地址,就会发生不同步的异常。所以尽量不要再迭代器迭代的时候修改集合中的数据,如果要修改,请使用循环。楼主的错误有二1.迭代器声明成全局的,首先就造成了迭代器的数据与集合不同步,因为集合是要发生变化的,必须是在变化后再进行迭代器的定向。
2.集合迭代的时候最好不要进行迭代删除的操作。如果进行删除操作,那么就不要在删除以后或者删除之前添加新的对象经集合中。对于第二个错误,楼主可以把action方法中的添加代码注释掉,然后运行一下看看。建议:请使用原来的循环代码。否则请使用观察者模式监听集合的变化,一旦有变化,则让Iterator的对象重新指向新集合的iterator。