简体   繁体   English

与迭代器的ConcurrentModificationException

[英]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 . 在每个部分,我都有一个使用DefaultTableModelJTable 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: 在这个特定的部分,我有三个:

  • one for the whole table 整个桌子一个
  • one containing only the free rooms 一个只包含免费房间
  • one only with the already booked rooms. 一个只有已预订的房间。

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: 你是:

  1. Creating an iterator 创建一个迭代器
  2. Modifying the list 修改列表
  3. Using the iterator after the list has been modified ← Error! 列表修改后使用迭代器←错误!

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: 一些不相​​关的观点:

  • Why are you writing things like extends java.awt.JFrame ? 为什么要编写extends java.awt.JFrame类的东西? Import it and use JFrame instead. 导入它并改为使用JFrame
  • Declare and initialize your variables when you need them. 在需要时声明并初始化变量。 If you had initialized the Iterator only in front of your for loop you wouldn't have had this problem. 如果你for循环前初始化了Iterator ,你就不会遇到这个问题。
  • Use generics ! 使用泛型 Non-generic 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.

相关问题 使用迭代器时出现ConcurrentModificationException - ConcurrentModificationException when using iterators 使用迭代器[.next()]时出现ConcurrentModificationException错误 - ConcurrentModificationException Error using Iterators [.next()] 使用2个迭代器的java.util.ConcurrentModificationException - java.util.ConcurrentModificationException using 2 iterators Java-具有递归方法和嵌套迭代器的ConcurrentModificationException - Java - ConcurrentModificationException with recursive method and nested iterators Java-解析具有2个迭代器和可怕的ConcurrentModificationException的ArrayList - Java - Parsing ArrayList with 2 iterators and the dreaded ConcurrentModificationException ConcurrentModificationException GL2 / update线程,带有同步和迭代器 - ConcurrentModificationException GL2/update thread, with sync and iterators 通过列表迭代,同步并使用迭代器时发生ConcurrentModificationException - ConcurrentModificationException on iteration through list, synchronized and using iterators Java,集合上的多个迭代器,删除正确的子集和ConcurrentModificationException - Java, multiple iterators on a set, removing proper subsets and ConcurrentModificationException Java迭代器如何检测集合被修改抛出ConcurrentModificationException? - How Java iterators detect the collection is modified to throw ConcurrentModificationException? 使用嵌套的迭代器删除没有ConcurrentModificationException的集合项 - Removing collection items without a ConcurrentModificationException using nested Iterators
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM