• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Paul Clapham
  • Tim Cooke
  • Jeanne Boyarsky
  • Liutauras Vilda
Sheriffs:
  • Frank Carver
  • Henry Wong
  • Ron McLeod
Saloon Keepers:
  • Tim Moores
  • Frits Walraven
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
Bartenders:
  • Al Hobbs
  • Piet Souris
  • Himai Minh

Collections iteration behavior

 
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Here's the code


package main.basics;

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

public class Collections {

/**
* @param args
*/
public static void main(String[] args) {
List<String> sampleSet = new ArrayList<String>();
String sequence = new String("a");
String postSequence = new String("b");
sampleSet.add(sequence);
sampleSet.add(postSequence);
System.out.println(sampleSet.size());
for (String element : sampleSet) {
System.out.println("Purging element " + element);
sampleSet.removeAll(java.util.Collections.singleton(element));
}
System.out.println(sampleSet.size());
}

}

---------
OUTPUT
---------
2
Purging element a
1



Can anyone tell me why is the collection not cleared completely?
 
Marshal
Posts: 76416
365
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
No. You tell me why you are removing anything from the List at all. An Iterator, which is what you are using in the for-each loop, is supposed to throw a ConcurrentModificationException if you add to or remove from a Collection while the Iterator is active. The only way you are supposed to remove anything is with the Iterator#remove() method. Why are you not suffering an exception?
You may get some help from the API for ConcurrentModificationException and Iterator.

By the way: I think this question is too difficult for "beginning", so I shall move it.
 
Shridhar Raghavan
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey.

Thanks for the reply. Revisited the code and changed it as below to find the ConcurrentModificationException being thrown. The change in a nutshell is i have repopulated the list to hold three elements "a","b","c".


However here is an observation, when the list contains just two elements {a,b} or duplicates {a,a,b} the code runs fine. Can you help me debug this? Working on it as we speak.yo


CODE



package main.basics;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Collections {

/**
* @param args
*/
public static void main(String[] args) {
// Create the list
List<String> sampleSet = new ArrayList<String>();
String sequence = new String("a");
String postSequence = new String("b");
sampleSet.add(sequence);
sampleSet.add("c");
sampleSet.add(postSequence);
// Let's examine the size
System.out.println(sampleSet.size());

// Try to modify using a iterative approach
for (int i = 0; i < sampleSet.size(); i++) {
String element = sampleSet.get(i);
System.out.println("Purging element " + element + " using an iterative approach");
sampleSet.removeAll(java.util.Collections.singleton(element));
}

// Re-examine the size
System.out.println(sampleSet.size());

// Clear everything out for our next exercise
sampleSet.clear();

sampleSet.add(sequence);
sampleSet.add("c");
sampleSet.add(postSequence);
System.out.println(sampleSet.size());

// Try to modify using an iterator this time
for (Iterator<String> element = sampleSet.iterator(); element.hasNext();) {
String elm = element.next();
if (elm instanceof String) {
element.remove();
System.out.println("Purging element " + elm + " using an iterator");

}
}
System.out.println(sampleSet.size());

sampleSet.add(sequence);
sampleSet.add("c");
sampleSet.add(postSequence);
System.out.println(sampleSet.size());

// Try to modify using an enhanced for loop
for (String element : sampleSet) {
System.out.println("Purging element " + element);
sampleSet.removeAll(java.util.Collections.singleton(element));
}
System.out.println(sampleSet.size());
}

}


OUTPUT

An exception was thrown. However if the list contains {a,b} or {a,a,b} the code works without an exception.
 
Shridhar Raghavan
Ranch Hand
Posts: 71
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I looked around and found a couple of comments on the for-each loop usage around collections.

Explanation


Excerpt :
Do not modify the list during iteration. While for-each syntax does not provide direct access to the iterator used by the equivalent basic for loop, the list can be modified by directly calling other methods on the list. Doing so can lead to indeterminate program behavior. In particular, if the compiler-inserted call to iterator() returns a fail-fast iterator, a java.util.ConcurrentModificationException runtime exception may be thrown. But this is only done a best-effort basis
 
Java Cowboy
Posts: 16084
88
Android Scala IntelliJ IDE Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Please UseCodeTags when you post source code.
 
Campbell Ritchie
Marshal
Posts: 76416
365
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Shridhar Raghavan wrote:I looked around and found a couple of comments on the for-each loop usage around collections.

Explanation . . .

Well done finding that good description of the for-each loop.
Debugging would be difficult because it would require getting into the code of the Iterator and ArrayList. You could write your own ArrayList and Iterator classes with debugging information, however.
The thing to explain is not why you don't remove both elements from your List. That is easy: When you have removed 1 element, the next index in the List would be 1, and an Iterator works on a while (index < size) . . . basis, because you are iterating an array. When index == 1 and size == 1, you will stop iterating. The hard part to explain is why you are not suffering a Concurrent ModificationException. You will have seen that the API doesn't guarantee such an Exception will actually be thrown, so this situation obviously breaks that rule.
 
Because those who mind don't matter and those who matter don't mind - Seuss. Tiny ad:
Garden Master Course kickstarter
https://coderanch.com/t/754577/Garden-Master-kickstarter
reply
    Bookmark Topic Watch Topic
  • New Topic