Jesse Yentsch
Jesse Yentsch

Reputation: 218

Removing an Element of a <String> ArrayList-Java

For a java homework assignment we were assigned to initialize an ArrayList of Strings containing dictionary words. If the words were not of a length we generated ,they are then to be removed from the ArrayList. The following code is not working.

public static int randLength() {
        int range=(RAND_MAX-RAND_MIN)+1;
        int randomNum=(int)(Math.random()*range)+RAND_MIN;
        return randomNum;
    }

This function works correctly.

int randomLength=randLength();
      System.out.println(randomLength);
      for(int i=0;i<dictionaryList.size()-1;i++) {
          if(dictionaryList.get(i).length()!=randomLength) {
              System.out.println("The lucky word is " + dictionaryList.get(i));
              dictionaryList.remove(i);
          }
      }

This however, does not. dictionaryList was initialized using a text file of words. Mine were, "apples" "beer" "charlie" "dogs" "elephant" "fogerty" In some cases, the code above does remove words that are not of the randomLength value. However it does not remove them all. Any help would be appreciated.

Upvotes: 1

Views: 405

Answers (3)

Phani Pulapa
Phani Pulapa

Reputation: 61

Java Collection classes are fail-fast, which means if the Collection will be changed while some thread is traversing over it using iterator, the iterator.next() will throw ConcurrentModificationException.

ie : it is not generally permissible for one thread to modify a Collection while another thread is iterating over it

To Avoid ConcurrentModificationException in multi-threaded environment

  1. You can convert the list to an array and then iterate on the array. This approach works well for small or medium size list but if the list is large then it will affect the performance a lot.
  2. You can lock the list while iterating by putting it in a synchronized block. This approach is not recommended because it will cease the benefits of multithreading.
  3. If you are using JDK1.5 or higher then you can use ConcurrentHashMap and CopyOnWriteArrayListclasses. This is the recommended approach to avoid concurrent modification exception

Consider below example which is fail fast

enter image description here

with ConcurrentHashMap:

enter image description here

Upvotes: 0

Makazau
Makazau

Reputation: 711

When you remove an item from the ArrayList, you are skipping over the next item in the list, and not checking if it should be removed.

For example, if you list is "apples", "beer", "charlie", "dogs", "atom", "elephant" and your random number for the length of the words that should be removed is 4 (beer, dogs, and atom should be removed), "atom" will not be removed. When the for loop runs, it runs as the following:

i: 0, word: "apples", not removed

i: 1, word: "beer", removed

i: 2, word: "dogs", removed

i: 3, word: "elephant", not removed.

If an element is removed, you must decrease i by 1 so all elements are checked. You can do this by putting i-- in the line after dictionaryList.remove(i)

This happens because when an element is removed from an ArrayList, all elements after it are shifted down to fill in the space, unlike an Array.

Additionally, your for loop should have i<dictionaryList.size() instead of i<dictionaryList.size()-1 in order to check the last element.

You could also use an Iterator to iterate through your ArrayList, but you probably don't want to use this if you weren't taught it yet.

Upvotes: 1

Miller Cy Chan
Miller Cy Chan

Reputation: 947

Better use iterator to remove elements to avoid concurrent modification exception.

int randomLength=randLength();
Iterator<String> iter = dictionaryList.iterator();
while(iter.hasNext()) {
    String word = iter.next();
    if(word.length() != randomLength) {
        System.out.println("The lucky word is " + word);
        iter.remove();
    }
}

Upvotes: 0

Related Questions