[英]ConcurrentModificationException with Iterators
I've been coding a program and I've faced several issues that I was able to address properly. 我一直在编写一个程序,我遇到了一些我能够正确解决的问题。 However, my program is throwing a
ConcurrentModificationException
and I'm not sure what I can do. 但是,我的程序抛出一个
ConcurrentModificationException
,我不知道我能做什么。
I'm coding with NetBeans 8.0.2 to create a Java desktop application (as required by my professor). 我正在使用NetBeans 8.0.2编写代码来创建Java桌面应用程序(根据我的教授的要求)。 The aim of the program is to manage a hotel.
该计划的目的是管理一家酒店。 So, it has some parts like "Customers", "Staff" and "Booking" (the one giving me problems).
因此,它有一些部分,如“客户”,“员工”和“预订”(给我带来问题的那个)。
On each part, I have a JTable
that uses a DefaultTableModel
. 在每个部分,我都有一个使用
DefaultTableModel
的JTable
。 In every part, I'm using files on the hard drive to make the changes persistent. 在每个部分中,我都在使用硬盘驱动器上的文件来使更改持久化。 I've coded new customer/staff classes.
我编写了新的客户/员工课程。 Now, I'm trying to code booking and unbooking methods.
现在,我正在尝试编码预订和取消预订方法。 Everything has gone pretty well until I got to the "unbooking" part.
在我进入“unbooking”部分之前,一切都很顺利。
After the table and model I have an ArrayList
. 在表和模型之后我有一个
ArrayList
。 In this particular part, I have three of them: 在这个特定的部分,我有三个:
The booking part was fine, I'm able to modify the table, the file and the ArrayList
without any errors, and my program actually does what it should. 预订部分很好,我能够修改表,文件和
ArrayList
没有任何错误,我的程序实际上做了应有的事情。 But I'm unable to get the unbooking part to work. 但我无法让unbooking部分工作。 It should basically be the reverse of booking.
它基本上应该与预订相反。
I will post a small part of my code, but if you need to know anything else or need some more parts of my code I would gladly share it. 我将发布我的一小部分代码,但如果您需要了解其他任何内容或需要我的代码的更多部分,我很乐意分享它。
My code: 我的代码:
public class GestionInstalaciones extends javax.swing.JFrame {
private final String ruta = System.getProperties().getProperty("user.dir");
private final File archivo = new File (ruta+"\\Instalaciones.txt");
private final DefaultTableModel modelo = new DefaultTableModel();
private final ArrayList contenidoInstalaciones;
private final ArrayList contenidoInstalacionesOcupadas;
private final ArrayList contenidoInstalacionesLibres;
public GestionInstalaciones() {
initComponents ();
contenidoInstalaciones = new ArrayList();
contenidoInstalacionesOcupadas = new ArrayList();
contenidoInstalacionesLibres = new ArrayList();
//Añadimos las columnas a la tabla.
modelo.addColumn ("Tipo");
modelo.addColumn ("Nombre Instalacion");
modelo.addColumn ("NIF del Ocupante");
cargarTabla();
}
private void cargarTabla(){
this.contenidoInstalaciones.clear();
FileReader fr = null;
BufferedReader br;
String tipo;
String nombre;
String NIFocupante;
String[] partes;
String linea;
try{
fr = new FileReader(archivo);
br = new BufferedReader(fr);
while ((linea=br.readLine())!=null) {
//Adding info to general ArrayList
this.contenidoInstalaciones.add(linea);
//Splitting line into 3 components.
partes = linea.split(",",3);
tipo = partes[0];
nombre = partes[1];
NIFocupante = partes[2];
//Skipping header.
if ( tipo.equals( "Tipo" )) { continue; }
//Añadimos la fila al modelo.
modelo.addRow(partes);
}
TablaInstalaciones.setModel(modelo);
}
//Capturamos excepciones y cerramos fichero.
catch(IOException e) {}
finally { try { if ( null != fr ) { fr.close(); } } catch (IOException e2){ } }
}//end cargarTabla()
private void botonLiberarInstalacionActionPerformed(java.awt.event.ActionEvent evt) {
Object linea;
int contador=0;
String aux;
String tiposATrabajar = "";
String[] tiposAInsertar;
Iterator instalacionesOcupadas;
//Cleaning of already booked ArrayList.
//this.contenidoInstalacionesOcupadas.clear();
instalacionesOcupadas = contenidoInstalacionesOcupadas.iterator();
this.comboTipoALiberar.removeAllItems();
this.comboTipoALiberar.addItem("Seleccione");
//Reading the general Table.
for (int z = 0; z < TablaInstalaciones.getRowCount() ; z++) {
//The booking parameter is on the 3rd place.
if(!TablaInstalaciones.getValueAt(z,2).equals("")){
//Putting the line into the ArrayList for booked rooms..
linea = TablaInstalaciones.getValueAt(z,0) + "," + TablaInstalaciones.getValueAt(z,1) + "," + TablaInstalaciones.getValueAt(z,2);
this.contenidoInstalacionesOcupadas.add(linea);
contador++;
}
}
**//Reading the booked ArrayList to put the right values on the combobox related.
//===> THIS LINE IS GIVING THE ERROR !!!
while(instalacionesOcupadas.hasNext()) {**
aux = instalacionesOcupadas.next().toString().split(",",3)[0];
//Checking to add only 1 kind of each room type.
if(!tiposATrabajar.contains(aux)); {
if (tiposATrabajar.equals("")) { tiposATrabajar=aux; }
else { tiposATrabajar = tiposATrabajar + "," + aux; }
}
}
//
tiposAInsertar = tiposATrabajar.split(",");
//Adding the type into the combobox.
for (String elemento: tiposAInsertar){ this.comboTipoALiberar.addItem(elemento.replace(",","")); }
}
ConcurrentModificationException
s happen when you make changes to a chain of elements (list) while you're actively looping through said chain. 当您正在循环遍历所述链时,对元素链(列表)进行更改时会发生
ConcurrentModificationException
。
I've encountered it often enough and always solve it by reverse looping through the list, that way you loop backwards and you can change or delete elements if you want without messing up the chain (list) you're looping over. 我经常遇到它并且总是通过反向循环遍历列表来解决它,这样你就可以向后循环,如果你想要的话你可以改变或删除元素而不会搞乱你循环的链(列表)。
I'd provide you with code, but I find it very hard to read yours, so this'll have to do for now. 我会为你提供代码,但我觉得很难读你的代码,所以现在必须这样做。
Hope this helps and good luck! 希望这有帮助,祝你好运!
If the contents of the Collection
you are iterating through have been changed since the last time you have used an iterator, you will get an exception if you try to use or reuse it. 如果自上次使用迭代器以来,您正在迭代的
Collection
的内容已经更改,那么如果您尝试使用或重用它,则会出现异常。 Create a new one - as a general rule, don't reuse an iterator . 创建一个新的 - 作为一般规则, 不要重用迭代器 。
You are: 你是:
You should modify the list before creating the iterator. 您应该在创建迭代器之前修改列表。
Also, you should try to minimize the scope of local variables . 此外,您应该尝试最小化局部变量的范围 。
As opposed to: 相反:
Iterator<String> someIterator = strings.iterator();
while (someIterator.hasNext()) {
doSomething();
}
You should probably do: 你应该这样做:
for (Iterator<String> iter = strings.iterator(); iter.hasNext();) {
doSomething();
}
Of course, if you (as you said) do not need to modify the list, use a for-each loop: 当然,如果您(如您所说) 不需要修改列表,请使用for-each循环:
for (String s : strings) {
doSomething();
}
Some unrelated points: 一些不相关的观点:
extends java.awt.JFrame
? extends java.awt.JFrame
类的东西? Import it and use JFrame
instead. JFrame
。 Iterator
only in front of your for
loop you wouldn't have had this problem. for
循环前初始化了Iterator
,你就不会遇到这个问题。 Collection
s will only err at run-time, while generic ones will give compile errors instead. Collection
只会在运行时出错,而泛型Collection
则会产生编译错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.