I want to know Different ways to remove element from Linked Hash Set. I tried following code
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
for(int i=0;i<10;i++)
lhs.add(String.valueOf(i));
Iterator<String> it=lhs.iterator();
System.out.println("removed?=="+lhs.remove("1"));
while(it.hasNext())
{
System.out.println("lhs"+it.next());
}
i got following output
removed?==true
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
at java.util.LinkedHashMap$KeyIterator.next(Unknown Source)
at preac.chapter1.Start.main(Start.java:321)
What i miss? thanks in advance.
P.S I have also tried iterator.remove() method but got Illegal State Exception
EDIT
I just came to know i have to use iterator remove method. then what it is use of Link Hash Set remove method ? In which cases we should use this method?
Try to remove element using Iterator.remove like below,
LinkedHashSet<String> lhs = new LinkedHashSet<String>();
for (int i = 0; i < 10; i++) {
lhs.add(String.valueOf(i));
}
Iterator<String> it=lhs.iterator();
// System.out.println("removed?=="+lhs.remove("1"));
while(it.hasNext()) {
String value=it.next();
if("1".equals(value)){
it.remove();
}
else{
System.out.println("lhs "+value);// Print the other value except 1
}
}
System.out.println(lhs);// After remove see the result here.
You get the exception because the iterator realizes that you called remove after creating the iterator (using an internal modification counter).
Let's assume add and remove increment the modification counter by 1.
When the iterator is created, it sees a modification counter of 10.
However, when the iterator is first accessed, the modification counter is 11, due to the call to remove, hence the exception.
Switch the statements and it should be fine:
...
System.out.println("removed?=="+lhs.remove("1"));
Iterator<String> it=lhs.iterator();
...
Related
All,
Running into the issue of ConcurrentModificationException and struggling to find a resolution partly because I can't see where I am modifiying the list while iterating it... Any ideas?? I've highlighted the line that is causing the issue (it3.remove()). Really at a standstill with this one..
EDIT: Stacktrace:
Exception in thread "Thread-4" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at com.shimmerresearch.advancepc.InternalFrameAndPlotManager.subtractMaps(InternalFrameAndPlotManager.java:1621)
Line 1621 corresponds to it3.remove() in my referenced code above.
private void subtractMaps(ConcurrentSkipListMap<String, PlotDeviceDetails> firstMap, ConcurrentSkipListMap<String, PlotDeviceDetails> secondMap) {
// iterate through the secondmap
Iterator<Entry<String, PlotDeviceDetails>> it1 = secondMap.entrySet().iterator();
while (it1.hasNext()) {
Entry<String, PlotDeviceDetails> itEntry = (Entry) it1.next();
String mapKey = (String) it1Entry.getKey();
PlotDeviceDetails plotDeviceDetails = (PlotDeviceDetails)it1Entry.getValue();
// if we find an entry that exists in the second map and not in the first map continue
if(!firstMap.containsKey(mapKey)){
continue;
}
// iterate through a list of channels belonging to the secondmap
Iterator <PlotChannelDetails> it2 = plotDeviceDetails.mListOfPlotChannelDetails.iterator();
while (it2.hasNext()) {
PlotChannelDetails it2Entry = it2.next();
// iterate through a list of channels belonging to the firstmap
Iterator <PlotChannelDetails> it3 = firstMap.get(mapKey).mListOfPlotChannelDetails.iterator();
innerloop:
while(it3.hasNext()){
// if a channel is common to both first map and second map, remove it from firstmap
PlotChannelDetails it3Entry = it3.next();
if(it3Entry.mChannelDetails.mObjectClusterName.equals(it2Entry.mChannelDetails.mObjectClusterName)){
it3.remove(); // this line is causing a concurrentModificationException
break innerloop;
}
}
}
}
}
plotDeviceDetails.mListOfPlotChannelDetails and firstMap.get(mapKey).mListOfPlotChannelDetails reference the same list.
Whether plotDeviceDetails and firstMap.get(mapKey) also reference the same object is unknown without more information, but they share the channel list.
The stack trace is showing that mListOfPlotChannelDetails is an ArrayList, and since the stack trace also shows that the error is coming from it3.remove(), and there is nothing in the code that can cause that, then you are truly facing a concurrent modification, i.e. another thread has updated the ArrayList being iterated by it3.
Remember, ArrayList does not support concurrent multi-thread access.
I have a very basic question.
I have created simple ArrayList and I am removing the item while iterating using for-each loop. It gives me java.util.ConcurrentModificationException because I can't remove an item while iterating but when I un-comment the if condition it works fine.
Please can anybody explain me how for-each works in this way.
ArrayList<String> list1 = new ArrayList<String>();
list1.add("Hello");
list1.add("World");
list1.add("Good Evening");
for (String s : list1) {
//if (s.equals("World")) {
list1.remove(1);
//}
}
If I change it to list1.remove(2); or list1.remove(0); then also its working fine.
Note: This is sample code and I know it will work fine using Iterator. My sole purpose of this question is to know how method remove() works perfectly if condition is un-commented no matter what index you are removing from the list.
The list has a variable called modCount, which means "modification count". Whenever you call remove (or perform other structural modifications), it increments the modCount.
The iterator can't keep track of its position in the list if you are adding or removing elements without telling the iterator. So as a safety check, at the start of iteration, the iterator makes a note of the modCount, saving it as expectedModCount. When each item is read from the iterator, the iterator checks to make sure the modCount still equals the expected value, and throws an exception if it doesn't.
Usually, this will successfully cause the exception to be thrown if the list is unsafely modified during iteration. However, it's not sufficient in this case when the if statement is enabled. After your code has read "World", that item is removed, and so the list now contains ["Hello", Good Evening"]. The iterator is still at position 1 (which now contains "Good Evening") and when it tries to read the next item, it finds it has now reached the end of the list, so it doesn't bother to check the modCount. Hence, no exception.
Note the caveat in the ConcurrentModificationException documentation: "It is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast operations throw ConcurrentModificationException on a best-effort basis."
Even if it doesn't happen to throw the exception in this case, the code is still wrong. To remove an element while iterating, you must use the iterator's own remove method:
for (Iterator<String> it = list1.iterator(); it.hasNext();) {
String s = it.next();
if (s.equals("World")) {
it.remove();
}
}
That way, the iterator knows that the list has changed and can still iterate correctly.
Alternatively, you can iterate from a temporary copy of the list:
for (String s : new ArrayList<>(list1)) {
if (s.equals("World")) {
list1.remove(...);
}
}
Although, in this simple case, you don't even need to do that; you can just write:
list1.remove("World");
You can also use an index-based removal. The drawback of this solution is that the list1.size() gets evaluated during every loop iteration. The positive thing is that removing an item from a List by its index is faster.
for (int i = 0; i < list1.size(); /* i incremented in loop body */) {
if ("World".equals(list1.get(i))) {
list1.remove(i);
}
else {
i++;
}
}
Use an Iterator and call remove():
Iterator<String> iter = list1.iterator();
while (iter.hasNext()) {
String str = iter.next();
if (someCondition)
iter.remove();
}
I am trying to iterate through a HashMap using 2 iterators. Firstly for every key(Integer) in the hash I compute "similar" numbers(it really doesn't matter what similar numbers are in this particular case) and then I have to delete the keys which are similar to the current key by making them values of the current key. I keep receiving this exception
Exception in thread "main" java.util.ConcurrentModificationException. What could be the cause? Do I have to use a ConcurrentHashMap?
This is the code I am compiling:
Set<Node> keySet = hash.keySet();
Iterator<Node> it = keySet.iterator();
while(it.hasNext()){
Node key = it.next();
ArrayList<Integer> similar = getAppropriateNum(key.getLabel(), 2);
for(int j = 0; j < similar.size(); j++){
Iterator<Node> it2 = keySet.iterator();
while(it2.hasNext()){
Node nod = it2.next();
if(nod.getLabel() == similar.get(j) && !nod.equals(key)){
it2.remove();
hash.put(key, nod);
}//end if
}//end while
}//end for
}//end while
The problem is that you are removing an item using an iterator (good practice) but the other iterator is not aware of that. Hence, the call to it.next() fails.
You should try to use only one iterator or remove items after looping.
EDIT : After analyzing your question, it seems that your need is to create a Collection of unique items. This makes me think that you would like to use a Set with a well-formed Comparator. In this way, adding all your items to your Set will automatically remove duplicates.
I wanted to display the numbers occuring in a character list and then remove that number. Here is my code:
package mytrials;
import java.util.ArrayList;
import java.util.ListIterator;
public class MyTrials {
public static void main(String[] args) {
ArrayList<Character> list = new ArrayList<Character>();
list.add('a');
list.add('1');
list.add('5');
System.out.println(list.size());
for( ListIterator i = list.listIterator(list.size()); i.hasPrevious();){
Character c = (Character) i.previous();
if( Character.isDigit(c)){
System.out.println(c + " is a digit");
list.remove(c);
}
}
System.out.println(list.size());
}
}
Here is the error message:
3
5 is a digit
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$ListItr.previous(AbstractList.java:386)
at mytrials.MyTrials.main(MyTrials.java:27)
Java Result: 1
What is the cause of this error and how can it be rectified.
Try
i.remove();
instead of
list.remove(c);
See here
Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.
Use Iterator instead of the for-each(loop) construct when you need to:
Remove the current element.
The for-each construct hides the iterator, so you cannot call remove. Therefore, the for-each construct is not usable for filtering.
Iterate over multiple collections in parallel.
Try to remove with your iterator :
i.remove(); // instead of list.remove(c);
The cause of the error is that the iterator's list was modified by using list.remove(c);.When a list is modified directly, the iterator becomes invalid, thus causing your error.
As Achintya Jha posted, you should use the iterator's remove function
list-iterator is a fail-fast iterator and throws an exception when a thread is trying to modify the list content while another thread is iterating it.
This might help
and this one
This question already has answers here:
Iterating through a Collection, avoiding ConcurrentModificationException when removing objects in a loop
(31 answers)
Closed 5 years ago.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(String st:li){
if(st.equalsIgnoreCase("str3"))
li.remove("str3");
}
System.out.println(li);
}
When I run this code,I will throw a ConcurrentModificationException.
It looks as though when I remove the specified element from the list, the list does not know its size have been changed.
I'm wondering if this is a common problem with collections and removing elements?
I believe this is the purpose behind the Iterator.remove() method, to be able to remove an element from the collection while iterating.
For example:
Iterator<String> iter = li.iterator();
while(iter.hasNext()){
if(iter.next().equalsIgnoreCase("str3"))
iter.remove();
}
The Java 8 way to remove it from the List without Iterator is:
li.removeIf(<predicate>)
i.e.
List<String> li = new ArrayList<String>();
// ...
li.removeIf(st -> !st.equalsIgnoreCase("str3"));
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will thow this exception
Taken from http://download.oracle.com/javase/1.4.2/docs/api/java/util/ConcurrentModificationException.html
yes people run into it -- the problem is you can't modify the list while iterating over it. I have used 2 alternatives in the past:
You can keep track of the indexes of the items you want to remove, and then remove them after you are done iterating.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
those options assume you have to iterate over the list to find the elements to remove -- useful in cases where the list elements are complex objects with properties you might test on.
In your particular case, you dont even need to iterate, as you can just use removeAll. Look at the API here. There are also nifty methods like retainAll that discard everything that is not in the argument. You can use remove/retain-like methods whenever the objects in the list implement equals and hashcode properly. If you cannot rely on equals/hashcode to identify equality between instances in your app, you will have to do the removal yourself....
Try this (Java 8):
list.removeIf(condition);
You could make a copy of list you want to remove element from, directly in for-each loop. For me, that is the simpliest way. Something like this:
for (String stringIter : new ArrayList<String>(myList)) {
myList.remove(itemToRemove);
}
Hope that will help you..
I think it is worth mentioning the Java 8 version
#Test
public void testListCur() {
List<String> li = new ArrayList<String>();
for (int i = 0; i < 10; i++) {
li.add("str" + i);
}
li = li.stream().filter(st -> !st.equalsIgnoreCase("str3")).collect(Collectors.toList());
System.out.println(li);
}
ArrayList has field modCount - count of collection modifications
When you invoke method iterator() creates new object Itr. It has field expectedModCount. expectedModCount field initialize by modCount value. When you invoke
li.remove("str3");
modCount increments. When do you try access to li via iterator
checks that expectedModCount == modCount
and if it is false throws ConcurrentModificationException
Hence if you get iterator and after collection modified - iterator is considered not valid and you cannot use it.
I think that best answer is from bigdev.de, but i would like to add something to it(like if the item is removed from a list, maybe you would like to log that somewhere or something):
List<String> list = new ArrayList<>();
list.removeIf(a -> {
boolean condition = a.equalsIgnoreCase("some condition");
if(condition)
logger.info("Item removed from the list: " + a);
return condition;
});
I got this problem and I think the easier way is the same with the second way that hvgotcodes gave.
Or you can copy all the ones you want to keep into a new list as you iterate, and then discard the old list when done.
#Test
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
List<String> finalLi = new ArrayList<String>();
for(String st:li){
if(st.equalsIgnoreCase("str3")){
// Do nothing
} else {
finalLi.add(st);
}
}
System.out.println(finalLi);
}
I looped a different way...
public void testListCur(){
List<String> li=new ArrayList<String>();
for(int i=0;i<10;i++){
li.add("str"+i);
}
for(int i=0; i<li.size(); i++)
if(li.get(i).equalsIgnoreCase("str3"))
li.remove(i--);
System.out.println(li);
}