This question already has answers here:
Why is a ConcurrentModificationException thrown and how to debug it
(8 answers)
Closed 8 years ago.
i got a problem with hashset, I cannot remove a hashset, and here is the code
//take stopword list from file
public void stopWordList(){
openFile("D:/ThesisWork/Perlengkapan/stopword.txt");
while(x.hasNext()){
String a = x.nextLine();
a = a.toLowerCase();
stopWords.add(a);
}
}
//the method to remove stopword
public void stopWordRemoval(){
stopWordList();
//if the word in the streams set is equal to stopword, it should be removed
for(String word:streams){
for(String sw:stopWords){
if(word.equals(sw)){
streams.remove(word);
}
}
}
But, it gives me an exception, it says like :
Exception in thread "main" java.util.ConcurentModificationException, could anyone help me? thanks :)
This is because the foreach loop (for (Whatever x: something)) internally creates an Iterator.
And when you remove from the Iterable (the something above) being iterated, a well-behaved Iterator will detect that "hey, you have modified my babies beyond my knowledge" and throw this exception.
What you should do is this:
final Iterator<String> iterator = stream.iterator();
String word;
while (iterator.hasNext()) {
word = iterator.next();
if (stopWords.contains(word))
iterator.remove(); // This is safe: an iterator knows how to remove from itself
}
you are performing a concurrent modification - you are iterating over a collection and modifiying it not by the iterator, you should transform your code to this:
for (Iterator<String> it = streams.iterator(); it.hasNext();) {
String word = it.next();
for (String sw : stopWords) {
if (word.equals(sw)) {
it.remove();
break;
}
}
}
Related
This question already has answers here:
Why is a ConcurrentModificationException thrown and how to debug it
(8 answers)
Closed 2 years ago.
I am facing java.util.ConcurrentModificationException while adding items to an existing list corresponding to a key
Here is my code
final Map<String, List<Apple>> feedToApplesMap = new HashMap<>();
for (final Apple Apple : AppleList) {
final List<String> feedDocumentIds = Apple.getFeedDocumentIds();
for (final String feedId : feedDocumentIds) {
final List<Apple> AppleListForFeed = feedToApplesMap
.getOrDefault(feedId, new ArrayList<>());
AppleList.add(Apple);
feedToApplesMap.put(feedId, AppleListForFeed);
}
}
I am unable to use iterator to solve this ? Any suggestions ?
I agree with #andbi that the question is due to a typo. But just for the exception, By doing so for (final Apple Apple : AppleList) you are still using Iterator unintentionally, that's why here AppleList.add(Apple); will throw ConcurrentModificationException, you can do it like this to avoid using Iterator:
final Map<String, List<Apple>> feedToApplesMap = new HashMap<>();
int size = AppleList.size();
for (int i = 0; i < size; i++) {
final Apple Apple = AppList.get(i);
final List<String> feedDocumentIds = Apple.getFeedDocumentIds();
for (final String feedId : feedDocumentIds) {
final List<Apple> AppleListForFeed = feedToApplesMap
.getOrDefault(feedId, new ArrayList<>());
AppleList.add(Apple);
feedToApplesMap.put(feedId, AppleListForFeed);
}
}
Please be aware that enhanced for-loop is just a syntatic sugar for for-loop with Iterator, the following two are the same:
for (Iterator<T> i = c.iterator(); i.hasNext(); )
for (T t : c)
Here is the document: The For-Each Loop
It seems like you're storing apples in a wrong place. Shouldn't it be
AppleListForFeed.add(Apple) instead of AppleList.add(Apple) ?
This happens when we are iterating a list using for loop or for each and some elements are added in between during iterating so use iterator or iterating a list:
val iterator = yourList.iterator()
while (iterator.hasNext()) {
val currentItem = iterator.next()
}
now add or delete any other element in your list during iterating.
This question already has answers here:
How to avoid "ConcurrentModificationException" while removing elements from `ArrayList` while iterating it? [duplicate]
(10 answers)
Closed 5 years ago.
I've been stuck on this for awhile now. I am trying to remove elements of a set if they make a set criteria. However when iterating when I try to remove the element it fails.
I get the java.util.ConcurrentModificationException
private static void smallerSet(Set<Map<String, Int>> set){
for (Map<String, Integer> map : set){
for (String String : map.keySet()){
if ( true){
set.remove(map);
}
else{
//System.out.println("test");
}
}
}
}
Any advice would be greatly appreciated.
You cannot remove elements from a Collection while iterating over it with the enhanced for loop.
You should use an explicit Iterator and remove with the Iterator's remove() method:
Iterator<Map<String, Integer>> iter = set.iterator();
while (iter.hasNext ()) {
Map<String, Integer> map = iter.next();
for (String str : map.keySet()){
if (some condition) {
iter.remove();
break; // you should probably break from the inner loop
// after removing an element
} else {
//System.out.println("test");
}
}
}
This question already has answers here:
List.remove strange behaviour
(4 answers)
Closed 7 years ago.
I am learning Java's Collection framework. I wrote this little program to check why we can't use For-each to remove elements.
Code:
import java.util.ArrayList;
class intro{
public static void main(String args[]){
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
for(String name:names){
names.remove(name);
}
for(String name:names){
System.out.println(name);
}
}
}
Outputs:
Saxena
And
import java.util.ArrayList;
class intro{
public static void main(String args[]){
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
names.add("Arvind");
for(String name:names){
names.remove(name);
}
for(String name:names){
System.out.println(name);
}
}
}
Throws:
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 intro.main(intro.java:15)
How come just the addition of one more element to collection is causing the error?
Normally when you remove an element from a collection while looping over the collection, you'll get a ConcurrentModificationException. This is partially why the Iterator interface has a remove() method. Using an iterator is the only safe way to modify a collection of elements while traversing them.
The code would go something like this:
ArrayList<String> names = new ArrayList<String>();
names.add("Rajat");
names.add("Saxena");
names.add("Arvind");
for (Iterator<String> iterator = name.iterator(); iterator.hasNext();) {
String string = iterator.next();
if (string.isEmpty()) {
iterator.remove();
}
}
Write a method removeEvenLength that takes a Set of strings as a parameter and that removes all of the strings of even length from the set.
My solution:
public static void removeEvenLength(Set<String> set) {
for(String word : set) {
if(word.length() % 2 == 0) {
set.remove(word);
}
}
}
Input:
[foo, buzz, bar, fork, bort, spoon, !, dude]
Output:
ConcurrentModificationException on line 2:
java.util.ConcurrentModificationException
at java.util.TreeMap$PrivateEntryIterator.nextEntry(TreeMap.java:1115)
at java.util.TreeMap$KeyIterator.next(TreeMap.java:1169)
at removeEvenLength (Line 2)
So I can solve it by creating an Iterator. But I want to know why the above code doesn't work?
EDIT:
Iterator doesn't work either:
public static void removeEvenLength(Set<String> set) {
Iterator<String> i = set.iterator();
while(i.hasNext()) {
String word = i.next();
if(word.length() % 2 == 0) {
set.remove(word);
}
}
}
Same error.
In this iteration iterator object is implicitly created. When you have iterator you can change collection just from iterator. In this case you are removing object directly, that's why this exception is thrown.
Create iterator, and remove object with iterator:
iterator.remove(); // removes current element
To understand why ConcurrentModificationException occurs, you will have understand the concept of fail-fast iteration. If a thread is iterating over a collection, and it realizes that the collection is being modified as the iteration is going on, the iterator will throw an exception rather than "probably" cause any integrity problems later on in the code.
Of course, not all iterators follow this approach, and using the Java Iterator will almost always ensure that the iteration never fails on modification.
To remove an element using the iterator, use this code
Iterator<String> iter = list.iterator();
while(iter.hasNext()) {
String obj = iter.next();
if(<removal_condition_here>) {
iter.remove();
}
}
This is a follow up to my previous question :
Collection - Iterator.remove() vs Collection.remove()
The below two pieces of code , which apparently differs only by a single line , but one throws exception and other don't . Can you please explain the difference ?
List<String> list = new ArrayList<String>
(Arrays.asList("noob1","noob2","noob3"));
System.out.println(list);
for (String str : list) {
if (str.equals("noob2")) {
list.remove(str);
}
}
runs fine , but if i change the condition to
if (!str.equals("noob2"))
the code throws exception !
What happens in this situation is you are removing the second list element.
List<String> list = new ArrayList<String>
(Arrays.asList("noob1", "noob2", "noob3", "noob4"));
System.out.println(list);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
if (str.equals("noob3")) {
System.out.println("Checking "+str);
list.remove(str);
}
}
System.out.println(list);
prints
[noob1, noob2, noob3, noob4]
Checking noob1
Checking noob2
Checking noob3
[noob1, noob2, noob4]
By removing the second last element you have reduced the size to the number of elements which you have iterated over.
// from ArrayList.Itr
public boolean hasNext() {
return cursor != size;
}
This causes the loop to exit early before the concurrent modifcation check is performed in next(). If you remove any other element next() is called and you get a CME.
BTW Something which also bypasses the check is
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
String str = iterator.next();
System.out.println("Checking "+str);
if (str.equals("noob2")) {
list.remove("noob1");
list.remove("noob3");
}
}
as long as the size of the collection is the same as the index it is up to, the check is not performed.
The for loop is just a simplified syntax for an iterator scan of the list. The iterator may throw an exception if the list is modified under it, but it is not guaranteed. Because of hasNext, iterators are often working one element ahead, making the first case less likely to be affected by list modification. By the time "noob2" is removed, the iterator already knows about "noob3".
Actually you should never remove collections' elements during "casual" iterating. When you have to modify your collection in some loop you have to use iterator to make these operations.
public class Test {
public static void main(String... args) {
List<String> list = new ArrayList<String>(Arrays.asList("noob1", "noob2", "noob3"));
System.out.println(list);
for (Iterator<String> iterator = list.iterator(); iterator.hasNext();) {
String str = iterator.next();
if (!str.equals("noob2")) {
iterator.remove();
}
}
System.out.println(list);
}
}
I suppose the exception is thown because you are trying to change a collection you are looping on... and not because the if condition.
I suggest you to create a new list only containing the items that verify the condition. Add them to the new list and avoid to change the original collection.
It's because you are trying to remove from a Collection you are currently iterating through. Making a minor alteration you can do what you want to do:
String[] strValues = {"noob1","noob2","noob3"}; // <<< Array
List<String> list = new ArrayList<String>(Arrays.asList(strValues));
System.out.println(list);
for (String str : strValues) { // << List is duplicate of array so can iterate through array
if (!str.equals("noob2")) {
list.remove(str);
}
}
That should work. Hopefully
Well, your first case doesn't throw the Exception because, the iterator returns false for Iterator.hasNext() at index 2 as you remove the element at index 1.
Iterator<String> itr = list.iterator();
while(itr.hasNext()){
String s= itr.next();
if(s.equals("noob2")){
list.remove(s); // size of the list is 2 here
System.out.println(itr.hasNext());// this returns false as it doesn't have anything at index 2 now.(on 2nd iteration )
}
}
You can test it clearly using a simple for-loop:
for (int i=0; i<list.size(); i++) {
if (list.get(i).equals("noob2")) {
System.out.println(list.get(i));
System.out.println(list.size());
list.remove(list.get(i));
System.out.println(list.size());
}
}
Output:
[noob1, noob2, noob3]
noob2
3
2
Notice the size of the list after you remove the element, which fails after incrementing. 2<2 which is false