0

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();
    }
}
robertoia
  • 2,301
  • 23
  • 29
Ni6htH4wk
  • 13
  • 1
  • "package" is a keyword, and as such is not a valid name for a package. – robertoia Apr 09 '14 at 19:57
  • quick fix: don't use iterator. – njzk2 Apr 09 '14 at 20:02
  • "package" is not the true package name I had to switch that out. And I know that I could not use an Iterator but it's more of a challenge. – Ni6htH4wk Apr 09 '14 at 20:03
  • @njzk2 That's not very good advice, because it begs the general question, "Why? Are iterators somehow bad?" and leaves a reader with a misleading view of iterators. – Jason C Apr 09 '14 at 20:03
  • yes, they are. They are clumsy, inconvenient, verbose, they throw exceptions all the time, and there is always something better to use instead. I never use them. (except implicitly in fast enumeration) – njzk2 Apr 09 '14 at 20:05
  • @Ni6htH4wk It's worth noting that "foreach" syntax works on anything that is `Iterable`, which is also the only type of thing that generically exposes an `Iterator`. So using `for (a : b)` does not impose additional constraints vs. using `Iterator` (it is essentially equivalent) - It still works for all `Iterable` (and thus all `Collection`, a sub-interface of `Iterable`). – Jason C Apr 09 '14 at 20:14
  • 1
    @JasonC, noted, but this is something that I was told to do with iterators, as I am learning about them before I take a course on them. I know the "foreach" but it was just something that I could not use in my Java classes. Thank you though! – Ni6htH4wk Apr 09 '14 at 22:10

2 Answers2

1

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.

Jason C
  • 38,729
  • 14
  • 126
  • 182
1

You are modifying the Collection named webster after the Iterator is created but before it is finished iterating. That causes the ConcurrentModificationException.

Considering that you don't need to iterate until you're in writer, just create a local Iterator there, so it won't be there to detect a modification.

PrintWriter out = new PrintWriter("words.txt");
Iterator<String> iter = webster.iterator();
while (iter.hasNext()) {
    out.println(iter.next());
}
out.close();
rgettman
  • 176,041
  • 30
  • 275
  • 357