I am working on a program which takes a text file as input and stores each word in a hash table along with a count of how many times the word occurs in the text. It seems to work fine until I attempt a file with more than 18 words, which results in a Concurrent Modification Exception.

Here is the code I have so far

/* WordCountLL.java template: Assignment 5 
   Implements hash table using buckets.  Java library data structure
   LinkedList used to implement buckets.
*/

import java.io.*;
import java.util.*;


public class WordCountLL
{
  public static final int TABLESIZE = 587;

// Next statement causes unsafe operation warning---don't like the known
// alternatives---rws

  public static LinkedList<WordItem> [] hashTable = new LinkedList [TABLESIZE];

/***************************************************************************/
// hash returns the hash value for the word stored in "word".
// The hash function is to sum the ASCII codes of the characters of the word
// MOD the hash table size.

  public static int hash(String word)
  {
    int i;
    int addr = 0;
    for (i = 0; i < word.length(); i++)
      addr += (int) word.charAt(i); 

    return addr % TABLESIZE;
  }

/***************************************************************************/

    public static void addWord(WordItem word, int addr)
    {
        ListIterator iter = hashTable[addr].listIterator();
        WordItem currWord;
        if(!(iter.hasNext()))
        {
            hashTable[addr].add(word);
            word.setCount(word.getCount() + 1);
        }
        else
        {
            while(iter.hasNext())
            {
                currWord = (WordItem)iter.next();
                if(currWord.getWord().equals(word.getWord()))
                {
                    word.setCount(word.getCount() + 1);
                    break;
                }
                else
                {
                    hashTable[addr].add(word);
                    word.setCount(word.getCount() + 1);
            }
            }
        }
    }

    /*public static WordItem maxCount(LinkedList list)
    {
        ListIterator iter = list.listIterator();
        int maxCount = 0;
        WordItem currWord = new WordItem();
        while(iter.hasNext())
        {
            currWord = (WordItem)iter.next();
            if(currWord.getCount() > maxCount)
            {
                maxCount = currWord.getCount();
            }
        }
        return currWord;
    }*/

    //public static 

  public static void main(String[] args)
  {
    //***** Hash table initialization goes here
        for(int i = 0; i < TABLESIZE; i++)
        {
            hashTable[i] = new LinkedList();
        }

    if (args.length < 2)
    {
       System.out.print("ERROR: insufficient number of command line ");
       System.out.println("arguments. Program aborted.");
       return;
    }

    int numWords = Integer.parseInt(args[1]);

    // Call book iterator with name of file (specified in args[0])
        BookIterator bookIterator = new BookIterator();
        bookIterator.readBook(args[0]);
    // Go through iterator storing words into hashtable
        while(bookIterator.hasNext())
        {
            WordItem word = new WordItem(bookIterator.next());
            addWord(word, hash(word.getWord()));
        }

    // Code for producing output goes here




        int totalWords = 0;
        for(int i = 0; i < TABLESIZE; i++)
        {
            totalWords = hashTable[i].size() + totalWords;
        }
        System.out.println("There were a total of " + totalWords + " unique words");

  }
}

For those who don't know, a java.util.ConcurrentModificationException is thrown by some iterators when they detect that the collection has been modified. Very few iterators can tolerate modifications happening to the thing they are trying to iterate over in the middle of iteration, so you don't allow one thread to modify a list while another thread is iterating through that list, and you certainly don't do something like line 57 where an item is added to the list in the middle of an loop that iterates over the list.

In other words, as soon as you modify a collection you must abandon all iterators you have for that collection because the next time you call a method on those iterators you will probably either get an unpredictable result or else a ConcurrentModificationException. Naturally the remove method of Iterator is allowed to modify a collection without ruining the iterator, but only for the one iterator on which the remove method is called; all other iterators should be discarded.

Finding the origin of an exception is easier if you include the line number of the exception in your question along with the source code. Doing that will tend to produce faster and more accurate answers.

This article has been dead for over six months. Start a new discussion instead.