Search code examples
javaarraylistiteratorconcurrentmodification

ConcurrentModificationException Error using Iterators [.next()]


I need some help with an iterator that it seems no matter what I do it keeps giving me the error:

Exception in thread "main" java.util.ConcurrentModificationException
 at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
 at java.util.ArrayList$Itr.next(ArrayList.java:831)
 at package.Dictionary.writer(Dictionary.java:72)
 at package.main.main(main.java:24) <5 internal calls>

I could use any help given to help solve this, I am somewhat new to Java programming. My full code is below:

package package;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.*;

public class Dictionary {
    Collection<String> webster = new ArrayList<String>();
    Iterator<String> iter = webster.iterator();
    File path = null;

    public Dictionary(Collection<String> words) {
        if (words == null) {
            throw new NullPointerException("Error: Collection NULL");
        } else {
            if (!words.isEmpty()) {
                clear();
            }
        }
    }

    public long load(File file) throws FileNotFoundException {
        String filePath = file.getAbsolutePath();
        if (file.getAbsolutePath().equals(null)
                || file.getAbsolutePath().equals("")) {
            throw new FileNotFoundException("Error: No File Found!");
        } else {
            if (file.exists()) {
                Scanner fileScanner = new Scanner(new File(filePath));
                long time = System.nanoTime();
                while (fileScanner.hasNext()) {
                    webster.add(fileScanner.next());
                }
                long time2 = System.nanoTime();
                long duration = time2 - time;
                return duration;
            } else {
                throw new FileNotFoundException("Error: No File Exsists!");
            }
        }
    }

    public boolean contains(String target) {
        if (webster.contains(target)) {
            return true;
        } else {
            return false;
        }
    }

    public void clear() {
        webster.clear();
    }

    public void writer() throws Exception {
        PrintWriter out = new PrintWriter("words.txt");
        while (iter.hasNext()) {
            out.println(iter.next());
        }
        out.close();
    }
}

Solution

  • The issue you are having now is because you are creating the iterator, then modifying the list by loading the dictionary, then using the iterator (which now throws the exception because the list was modified after the iterator was created).

    You have your Iterator as an instance variable and you are instantiating it on initialization. You don't want to do this here. Instead, create the Iterator in the method you are using it in, e.g. get rid of the instance variable and do:

    public void writer() throws Exception {
        PrintWriter out = new PrintWriter("words.txt");
        Iterator<String> iter = webster.iterator();
        while (iter.hasNext()) {
            out.println(iter.next());
        }
        out.close();
    }
    

    Or, even clearer, and without the use of an explicit Iterator, simply do:

    public void writer() throws Exception {
        PrintWriter out = new PrintWriter("words.txt");
        for (String entry : webster)
            out.println(entry);
        out.close();
    }
    

    An iterator is just a temporary object that can be used for iterating over a collection of items, it does not need to stick around. Create one when you need it, then forget about it when you're done with it.