ConcurentModificationException while adding items in a map [duplicate] - java

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.

Related

ConcurrentModificationException When removing element using list iterator java

I have an issue removing the 1st and 2nd element of my list even by using the iterator.
I have read the following threads but can't fix my issue (those were the most relevant but I checked other material as well):
ConcurrentModificationException when trying remove element from list
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
So my code looks like this:
List<List<String>> list = cnf.read();
List<List<String>> nlist = new ArrayList<>();
for (List<String> l : list) {
if (l.size() <= 3) {
nlist.add(l);
} else {
int size = l.size();
while (size > 3) {
List<String> three = l.subList(0, 2);
three.add("Y" + (count++));
//Iterator itr = l.iterator();
ListIterator itr = l.listIterator();
int v = 0;
while (itr.hasNext()) {
itr.next();
if (v == 0 || v == 1) {
itr.remove();
v++;
}
}
l.add(0, "Y" + (count++));
size--;
nlist.add(three);
}
nlist.add(l);
}
}
for (List<String> l : nlist) {
System.out.println(l.toString());
System.out.println(l.size());
}
I get a ConcurrentModificationException at the print statement here :
System.out.println(l.toString());
I tried using iterators for my 2 for loops as well but It doesn't seem to make a difference!
I am new to posting questions so let me know If I am doing it right!
Thank you.
After A long debugging, here is the solution.
The sublist function passes by reference and not by value, a sublist created by ArrayList.subList call keeps a reference to the original list and accesses its elementData array directly.
For this reason, when adding an element to the "three" list, we alter the state of the original list. this happens here:
three.add("Y" + (count++));
A way of fixing it for this specific case is to create and initialize the "three" list the following way:
String one = l.get(0);
String two = l.get(1);
List<String> three = new ArrayList<>();
three.add(one);
three.add(two);
three.add("Y" + (count));
This allows us to manipulate our lists without getting Concurrency Exceptions (ConcurrentModificationException). However, if you are manipulating big lists, I would suggest you use another less hardcoded method for list creation.
I will mark this thread as answered and hope it helps people.

How to remove duplicate values in ArrayList with original element [duplicate]

This question already has answers here:
How do I remove repeated elements from ArrayList?
(40 answers)
Closed 5 years ago.
Suppose I have an ArrayList, which has paths to the specific file to be processed. But this file can only be proccessed, if there's only one in a folder. Here's what I mean:
My ArrayList
List<String> pathsToTheFile = new ArrayList<>();
has
C:\123\456\NameOfUniqueFolder0
C:\123\456\NameOfUniqueFolder1
C:\123\456\NameOfUniqueFolder2
C:\123\456\NameOfUniqueFolder3
C:\123\456\NameOfUniqueFolder4
Suppose my 5th element is
C:\123\456\NameOfUniqueFolder0
Obviosuly, it's a duplicate of my 0 element, since the file inside this folder SHOULD NOT be proccessed at all. C:\123\456\NameOfUniqueFolder0 should be removed form the list. I can not use a SET here, because it will "remove" the duplicate, but one path to the folder will be still there, and the file inside get proccessed.
Using a hashmap here might make sense. The keys could be the file paths, and the value, if the key be present, would be the number of times the file occurs. Something like this:
Map<String, Integer> map = new HashMap<>();
map.put("C:\123\456\NameOfUniqueFolder0", 1);
map.put("C:\123\456\NameOfUniqueFolder1", 1);
map.put("C:\123\456\NameOfUniqueFolder2", 1);
map.put("C:\123\456\NameOfUniqueFolder3", 1);
map.put("C:\123\456\NameOfUniqueFolder4", 1);
Now when a new path comes along, increment its counter:
String newPath = "C:\123\456\NameOfUniqueFolder0";
Integer val = map.get(newPath);
map.put(newPath, val == null ? 1 : val.intValue() + 1);
}
At the end, you can iterate this map, and check the counter values for each key. You would then only process the files having occurred only once:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
int count = entry.getValue();
if (count == 1) {
// process this file
}
// otherwise skip this path
}
You can do something like this:
public class RemoveDuplicatesFromList {
public static void main(String[] args) {
List<String> originalList = new ArrayList<String>();
//add your strings to list here
Set<String> duplicateValues = new HashSet<String>();
for(String str:originalList){
//if firstIndex != lastIndex duplicate is present
if(originalList.indexOf(str)!=originalList.lastIndexOf(str))
duplicateValues.add(str);
}
//remove duplicates from original list
originalList.removeAll(duplicateValues);
System.out.println(originalList);
}
}
You can do something like below. it will give you map of path with it's number of occurrence. eg: {C:\123\456\NameOfUniqueFolder0=2, C:\123\456\NameOfUniqueFolder1=1}
Map<String, Long> collect = pathsToTheFile.stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
After this you can process only path having occurrence equal to 1.
you can use only HashSet for this if you want list in sorted order the use TreeSet
HashSet<String> set=new HashSet<String>();
set.add("C:\123\456\NameOfUniqueFolder0");
set.add("C:\123\456\NameOfUniqueFolder1");
set.add("C:\123\456\NameOfUniqueFolder2");
set.add("C:\123\456\NameOfUniqueFolder3");
set.add("C:\123\456\NameOfUniqueFolder4");
set.add("C:\123\456\NameOfUniqueFolder0");
//Traversing elements
Iterator<String> itr=set.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
your output will be
C:\123\456\NameOfUniqueFolder0
C:\123\456\NameOfUniqueFolder1
C:\123\456\NameOfUniqueFolder2
C:\123\456\NameOfUniqueFolder3
C:\123\456\NameOfUniqueFolder4
You can try this code
List<String> pathsToTheFile = new ArrayList<String>();
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder0");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder1");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder2");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder0");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder3");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder4");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder0");
pathsToTheFile.add("C:/123/456/NameOfUniqueFolder0");
String newPathToBeAdded = "C:/123/456/NameOfUniqueFolder0";
while(pathsToTheFile.contains(newPathToBeAdded)) { // the new path to be added
pathsToTheFile.remove(newPathToBeAdded);
}
System.out.println(pathsToTheFile);

Removing a set from it self while iterating [duplicate]

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");
}
}
}

How to remove items in list based on poja class values

How to remove the list items from list like below
List<Mypojaclass> results = new ArrayList<>();
// in the results i am adding more items using sql query, after that,
if(Mypojaclass sensor : results){
if(sensor.getType.equals("JD"){
sensor.remove(sensor);
}
}
I can do it using iterator if its like below,
List<String> results = new ArrayList<>();
for (Iterator<String> iter = list.listIterator(); iter.hasNext(); ) {
String a = iter.next();
if (...) {
iter.remove();
}
}
But i should remove the items based on that sensor.getType only.
How can i achieve this?
Using Java 8 you can do this:
results = results.stream().filter(p ->! p.getType().equals("JD")).collect(Collectors.toList());
For Java 7 and below the safest bet would be:
Iterator<Mypojaclass> itr = results.iterator();
while(itr.hasNext()){
Mypojaclass item = itr.next();
if("JD".equals(item.getType())){
itr.remove();
}
}
I decided to give an answer because the others seem to struggle with the lists, iterators, streams, and so on.
First, the problem:
A code snippet like this
List<Mypojaclass> results = ...;
for (Mypojaclass sensor : results) {
if (sensor.getType.equals("JD") {
results.remove(sensor); // <-- possible CME here
}
}
is buggy because it simply can throw a ConcurrentModificationException. The reason is that the for-each-loop uses an iterator, so the above code is equivalent to the following code that uses an explicit iterator:
List<Mypojaclass> results = ...;
for (Iterator<Mypojaclass> itr = result.iterator(); itr.hasNext(); ) {
Mypojaclass sensor = itr.next();
if (sensor.getType.equals("JD") {
results.remove(sensor);
}
}
Note, that you call remove on the list, not on the iterator. The iterator then throws the CME because the list was changed outside the iterator.
The solution:
Call the remove operation on the iterator:
List<Mypojaclass> results = ...;
for (Iterator<Mypojaclass> itr = result.iterator(); itr.hasNext(); ) {
Mypojaclass sensor = itr.next();
if (sensor.getType.equals("JD") {
itr.remove();
}
}
Now this code snippet iterates once through the whole list while simultaneously removing all occurrences of sensors whose type equals to "JD".
Java 8 code:
As we are now in the Java 8 time aera, this will do the same in Java 8:
results.removeIf(s -> s.getType().equals("JD"));
Or - with the help of a stream and some filtering:
List<Mypojaclass> filtered = results
.stream()
.filter(s -> !s.getType().equals("JD"))
.collect(Collectors.toList());
results = filtered;
Note here, that the filter predicate has to be negated. You don't want to have the "JD" types. You want to have all the other types.
For Java 8:
results.removeIf(f -> f.getType().equals("JD"));
Removes all items from the list having a type of "JD"
For plain Java 7:
List<Mypojaclass> filteredResults = new ArrayList<>();
for (Mypojaclass item: results) {
if (!item.getType().equals("JD")) {
filteredResults.add(item);
}
}
Alternative
Iterator<Mypojaclass> iterator = results.iterator();
while (iterator.hasNext()) {
Mypojaclass item = iterator.next();
if (item.getType().equals("JD")) {
iterator.remove();
}
}
Now filtered Results contains the filtered list.
In case of Java 7 you could also think about using commons-collections which contains methods to achieve those filtering mechanism.
results.stream().filter(p -> p.getType().equals("JD"));
from the above comment does nothing. You would need to collect the items in a new list and you would have to negate the filter predicate because otherwise you would end up with a collection with just elements that have a type of "JD"
I know this is not the neatest but I think it works
List<Mypojaclass> results = new ArrayList<Mypojaclass>();
Mypojaclass [] placeHolder = null; //this will hold the object(s) to be removed
int length = 0; //this will hold the length of this new array of placeHolder array
for (Mypojaclass sensor : results) {
if(sensor.getType.equals("JD"){
length++;
}
}
placeHolder = new Mypojaclass[length]; //allocates memory
for (Mypojaclass sensor : results){
if(sensor.getType.equals("JD"){
placeHolder[length-1] = sensor; //initialize
length--;
}
}
//This will remove all instances when getType equals "JD"
for(int i = 0; i < placeHolder.length; i++){
results.remove(placeHolder[i]);
}
Just use a for loop:
List<Mypojaclass> results = new ArrayList<>();
// in the results i am adding more items using sql query, after that,
for(int i = 0; i < results.size(); i++) {
if(results.get(i).getType.equals("JD"){
results.remove(i);
}
}
Or just use the Iterator directly:
List<Mypojaclass> results = new ArrayList<>();
// in the results i am adding more items using sql query, after that,
Iterator<Mypojaclass> iterator = results.iterator()
while(iterator.hasNext()) {
if(iterator.next().getType().equals("JD"){
iterator.remove();
}
}

Cannot remove hashset in java [duplicate]

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;
}
}
}

Categories