0

Hi I am making a project which reads a list of books from file and I want to add possibility to add new book when button is pressed. But I get many errors. Look at my code:

public class Biblioteka {

    public static void main(String[] args) {

        JFrame frame = new JFrame("Biblioteka");
        frame.setVisible(true);
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        frame.add(panel);
        GridBagConstraints c = new GridBagConstraints();

        JButton button = new JButton("Print List");
        JButton button2 = new JButton("Add book");

        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(10, 10, 10, 10);

        panel.add(button);
        panel.add(button2);

        final List<Book> listofbooks = new ArrayList<>();

        try {
            File file = new File("newfile.txt");
            Scanner input = new Scanner(file);
            while (input.hasNextLine()) {
                String input1 = input.nextLine();// read one line
                String num[] = input1.split("\\|");// split line by "|"
                int howMuch = Integer.parseInt(num[2]);
                Book k1 = new Book(num[0], num[1], howMuch);

                listofbooks.add(k1);
            }
        } catch (FileNotFoundException nf) {
            System.err.format("File does not exist");
        }

        final JLabel labelis = new JLabel();
        for (Book book : listofbooks) {

            labelis.setText("<html> "
                    + labelis.getText()
                    + "<br> Name: " + book.getName()
                    + " Tile: " + book.getTitle()
                    + " Number of books: "
                    + book.getHowMany()
            );

        }
        labelis.setText(labelis.getText() + "</html>");
        button.addActionListener(new Action() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFrame frame2 = new JFrame("Clicked");
                frame2.setVisible(true);
                frame2.setSize(400, 300);
                JPanel panelis = new JPanel();
                panelis.add(labelis);
                frame2.add(panelis);
            }
        });

The program crashes here when I want to add a new book:

        button2.addActionListener(new Action() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String knygAutorius = JOptionPane.showInputDialog("Input author: ");
                String knygPav = JOptionPane.showInputDialog("Input title: ");
                int knygKiek = Integer.parseInt(JOptionPane.showInputDialog("How many books do you want to add: "));
                int i = 0;
                for (Book book : listofbooks) {
                    if ((book.getTitle().equals(knygPav)) && (book.getName().equals(knygAutorius))) {
                        int kiekis = book.getHowMany();
                        kiekis = kiekis + knygKiek;
                        Book k2 = new Book(knygAutorius, knygPav, kiekis);
                        listofbooks.set(i, k2);
                    } else {
                        Book nauja = new Book(knygAutorius, knygPav, knygKiek);
                        listofbooks.add(nauja);
                    }
                    i++;

                }
            }
        });

    }

    static class Action implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }
}

And I have one class Book:

public class Book {

    String name;
    String bookTitle;
    int howMany;

    public Book(String name, String bookTitle, int howMany) {
        this.name = name;
        this.bookTitle = bookTitle;
        this.howMany = howMany;
    }

    public String getName() {
        return this.name;
    }

    public String getTitle() {
        return this.bookTitle;
    }

    public int getHowMany() {
        return this.howMany;
    }

}

You can try to compile my code and see the problem. Maybe you could help me. Errors:

Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
    at java.util.ArrayList$Itr.next(ArrayList.java:831)
    at biblioteka.Biblioteka$2.actionPerformed(Biblioteka.java:83)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6505)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3320)
    at java.awt.Component.processEvent(Component.java:6270)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4861)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2719)
    at java.awt.Component.dispatchEvent(Component.java:4687)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:735)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:708)
    at java.awt.EventQueue$4.run(EventQueue.java:706)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:705)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)
6
  • Please post your errors Commented Mar 19, 2014 at 19:13
  • @VinceEmigh edited my post. Take a look Commented Mar 19, 2014 at 19:16
  • I tried running it, and I didn't get any errors. Although your for(Book book : listofbooks) never triggers (are there any books in there?). It doesn't seem as if you add the book in before going through the loop. Commented Mar 19, 2014 at 19:28
  • Yup there are books. I changed loop for (Book book : listofbooks) to for (int i = 0; i<listofbooks.size(); i++) and added some minor changes. Now I didn't get any errors. But it's interesting how you do not get any errors with my first code Commented Mar 19, 2014 at 19:35
  • Yeah, I had a friend that fixed that same error simply by changing his loop. Although, since it IS a ConcurrentModException, I gotta point out that you aren't handling any of your UI on the EDT. You should look into SwingUtilities.invokeLater() and invokeAndWait() to learn about how to handle Swing Components. There is a thread that runs your code, but there is also a Thread dedicated to Swing events called the Event Dispatch Thread. I highly suggest you look into it. docs.oracle.com/javase/tutorial/uiswing/concurrency/… Commented Mar 19, 2014 at 19:39

1 Answer 1

1

Got that,why you are getting the above error is you are adding a new book to that list and again calling on the same list in for loop because of this you are getting

**java.util.ConcurrentModificationException**


import java.awt.GridBagConstraints;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.io.File;
import java.io.FileNotFoundException;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;


public class Biblioteka {

    public static void main(String[] args) {

        JFrame frame = new JFrame("Biblioteka");
        frame.setVisible(true);
        frame.setSize(400, 400);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel();
        frame.add(panel);
        GridBagConstraints c = new GridBagConstraints();

        JButton button = new JButton("Print List");
        JButton button2 = new JButton("Add book");

        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(10, 10, 10, 10);

        panel.add(button);
        panel.add(button2);

        final List<Book> listofbooks = new ArrayList<Book>();

        try {
            File file = new File("d:\\a.txt");
            Scanner input = new Scanner(file);
            while (input.hasNextLine()) {
                String input1 = input.nextLine();// read one line
                String num[] = input1.split(" ");// split line by "|"
                int howMuch = Integer.parseInt(num[2]);
                client.Book k1 = new client.Book(num[0], num[1], howMuch);

                listofbooks.add(k1);
            }
        } catch (FileNotFoundException nf) {
            System.err.format("File does not exist");
        }

        final JLabel labelis = new JLabel();



        button.addActionListener(new Action() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFrame frame2 = new JFrame("Clicked");
                frame2.setVisible(true);
                frame2.setSize(400, 300);
                JPanel panelis = new JPanel();

                panelis.add(labelis);
                    //Moving for loop inside,so latest update on the books will be printed
                    //This is the reason you are not getting the modified count before
                    for (Book book : listofbooks) {

                        labelis.setText("<html> "
                                + labelis.getText()
                                + "<br> Name: " + book.getName()
                                + " Tile: " + book.getTitle()
                                + " Number of books: "
                                + book.getHowMany()
                        ); 
                }

                labelis.setText(labelis.getText() + "</html>");
                frame2.add(panelis);

            }
        });



        button2.addActionListener(new Action() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String knygAutorius = JOptionPane.showInputDialog("Input author: ");
                String knygPav = JOptionPane.showInputDialog("Input title: ");
                int knygKiek = Integer.parseInt(JOptionPane.showInputDialog("How many books do you want to add: "));
                int i = 0;
                for (Book book : listofbooks) {
                    if ((book.getTitle().equals(knygPav)) && (book.getName().equals(knygAutorius))) {
                        int kiekis = book.getHowMany();
                        kiekis = kiekis + knygKiek;
                        book.setHowMany(kiekis);
                        break;
                    } 
                    i++;
                }

                if(listofbooks.size()==i){
                     Book nauja = new Book(knygAutorius, knygPav, knygKiek);
                     listofbooks.add(nauja);
                }
            }
        });

    }

    static class Action implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {

        }
    }


}

And small modification in Book.java to set the number of books

public class Book {

    String name;
    String bookTitle;
    int howMany;

    public Book(String name, String bookTitle, int howMany) {
        this.name = name;
        this.bookTitle = bookTitle;
        this.howMany = howMany;
    }

    public String getName() {
        return this.name;
    }

    public String getTitle() {
        return this.bookTitle;
    }

    public int getHowMany() {
        return this.howMany;
    }
    //to set the total books
    public void setHowMany(int total){
        howMany=total;
    }

}
Sign up to request clarification or add additional context in comments.

4 Comments

Just wondering, but listofbooks isn't synchronized, nor is the loop, and I don't think a loop can acquire an object's lock just by being a loop. Please correct me if I'm wrong, but wouldn't ConcurrentModEx be thrown if a thread attempts to affect an object while another Thread has the lock?
The threading doesn't have anything to do with it. An ArrayList Iterator can throw this exception if the list is structurally modified(usually an add or remove) by anything other than the iterator's own add/remove methods during the iteration. docs.oracle.com/javase/6/docs/api/java/util/ArrayList.html
@RKC it doesn't work if I add book with same author and title. It merely adds a new book to the end of the list, but not increases the ammount of these books
I edited my post.check that.There are few more mistakes in your code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.