Here is my code. I have an arraylist of visited elements. So I want delete these visited elements from the hashmap and below is code. It gives me concurrentmodification exception.
private static void removeVisitedNodes(ArrayList<String> arrayList) {
// TODO Auto-generated method stub
Iterator<String> it = arrayList.iterator();
String temp;
while(it.hasNext())
{
temp = it.next();
System.out.println("temp is " + temp);
Iterator<Entry<String, ArrayList<String>>> iter = neighbours_reachability_map.entrySet().iterator();
// iterate through the hashmap to remove elements
while (iter.hasNext()) {
Entry<String, ArrayList<String>> entry = iter.next();
if(entry.getValue().contains(temp)){
//System.out.println("Contains it" + entry.getValue().toString());
entry.getValue().remove(temp);
}
}
}
}
I checked up a few other similar questions but they did not help much. Is there a neater way to do this without causing an exception? Thanks in advance for your help.
To remove a element whilst in the middle of iterating, use Iterator.remove().
you can put the elementos you want to delete in another collection object and then, after finished the iteration, delete those elements
Related
If I run the following code, it will print out 3 times duplicate, but when I remove the if statement inside the while loop (just to see how many times it will iterate) it starts an infinite loop.
How does actually this hasNext() method working? I thought that will iterate only 5 times as I have 5 items in the list.
public class ExerciseOne {
public static void main(String []args){
String []colors = {"MAGENTA","RED","WHITE","BLUE","CYAN"};
List<String> list = new ArrayList<String>();
for(String color : colors)
list.add(color);
String[] removeColors = {"RED","WHITE","BLUE"};
List<String> removeList = new ArrayList<String>();
for(String color : removeColors)
removeList.add(color);
removeColors(list,removeList);
System.out.printf("%n%nArrayList after calling removeColors:%n");
for(String color : list)
{
System.out.printf("%s ",color);
}
}
private static void removeColors(Collection<String> collection1, Collection<String> collection2)
{
Iterator<String> iterator = collection1.iterator();
while(iterator.hasNext()){
if(collection2.contains(iterator.next()))
System.out.println("duplicate");
}
}
}
It is pretty simple, actually
while(iterator.hasNext()){
if(collection2.contains(iterator.next()))
System.out.println("duplicate");
}
Imagine that the iterator is a pointer to an element of your list.
When you call next(), you're moving this pointer one step ahead.
If you don't move the pointer, hasNext() will always be true because you're still in the beginning of the list.
So you have to call the iterator's next() until there isn't any remaining element in the list.
If you remove the if statement, then it will go for an infinite loop since your iterator.next() is in the if condition. Actually iterator.next() is the api that moves the pointer, not the hasNext(). hasNext() just checks if there is any element in the collection. Since removal of the if statement is also removing the hasNext api, the pointer to the collection is not moving and hasNext is always returning true.
If you take out the iterator.next() from the if condition and move it above the if condition, then the loop will iterate for 5 times even after you remove the if statement.
Iterator<String> iterator = collection1.iterator();
while(iterator.hasNext()){
String currentColor = iterator.next();
if(collection2.contains(currentColor)){
System.out.println("duplicate");
}
}
The question why Iterator is important/introduced is simple:
consider following example:
List<String> list = new ArrayList<String>();
list.add("Anurag");
list.add("Soni");
list.add("MMM");
list.add("GKP");
for(string s : list){
if(s.equals(" Anurag")
s.remove();
System.out.println(s);
}
This will throw an exception-`Concurrent Modification exception` as you are trying to alter the structure of the data structure List before the iteration is completed.
so you may use Iterator for the same purpose .
Iterator iterator = List.iterator();
while(iterator.hasNext()){
String current = iterator.next();
if(current=="Anurag"){
iterator.remove();
}else{
System.out.println(current);
}
}
OUTPUT: Soni
MMM
GKP
This question already has answers here:
Collection throws or doesn't throw ConcurrentModificationException based on the contents of the Collection [duplicate]
(5 answers)
Closed 6 years ago.
I have tried the following two scenarios:
ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("1")) {
arrayList.remove(0);
}
}
The first scenario output is :
---->1
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
at java.util.ArrayList$Itr.next(Unknown Source)
at Test.main(Test.java:83)
Probably the ConcurrentModificationException exception is caused because I'm trying to modify the collection while I'm still iterating it.
In the second scenario I changed the if() condition from value.equals("1") to value.equals("2") and the program does not throw any error.
ArrayList arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
arrayList.remove(0);
}
}
The second scenario output is:
---->1
---->2
In both the scenarios, my program does not reach the 3rd element (Value : 3).
Can you please help me to understand the problem ?
Problem is you are removing element from the list which presend at index 0. Instead of removing from the list use iterator.remove() method. For more info read this.
program code -
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
iterator.remove();
}
}
Why list not returning the last element?
Answer -
you are removing element from the list and you already perform iterator action against same list. At the end iterator.hasnext() method returns false so you are not getting last element.
If you want to see it for demo purpose run below sample codes -
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
arrayList.remove(0);
}
}
System.out.println("ArrayList : "+arrayList);
output -
---->1
---->2
ArrayList : [2, 3]
List arrayList = new ArrayList();
arrayList.add("1");
arrayList.add("2");
arrayList.add("3");
Iterator iterator = arrayList.iterator();
while (iterator.hasNext()) {
String value = (String) iterator.next();
System.out.println("---->" + value);
if (value.equals("2")) {
iterator.remove();
}
}
System.out.println("ArrayList : "+arrayList);
output -
---->1
---->2
---->3
ArrayList : [1, 3]
By running two pieces of code in debug mode, I found the following.
1st scenario:
Elements saved from arraylist:
After the remove command has been executed:
The ConcurrentModificationException gets thrown at the following line
String value = (String) iterator.next();
2nd Scenario:
The ArrayList will be the same as the second link.
After printing 2, the control breaks from
while (iterator.hasNext())
as iterator.hasNext() = null. Hence it's safe.
I suppose that you encounter the problem only in the first case because you are trying to remove the element pointed by the iterator. In fact, the second scenario succeeds because you remove the first arraylist element that, at that moment, is not pointed by the iterator.
(p.s. I agree with all the various and future answers that will describe you how to solve your problem by showing fragments of code, I just provided you an explanation of what happens)
The ConcurrentModificationException occurs because you are removing the same element (at index 0) that the current iteration of the loop is reading (the one with value = ”1”). In the second case you don't see the exception because you are removing the element at index 0, but are reading the element at index 1 (the one with value = "2"). You cannot remove an element concurrently while reading it unless you use one of the collections that supports concurrency (see java.util.concurrent package)
You are removing an element (remove(0)) while iterating the list, which "shifts the end of the list" towards left by one. So, the next time you check for iterator.hasNext(), it will return false and the original 3rd element never gets processed.
When you iterate on a Collection, you should remove the element with the iterator :
iterator.remove()
In the second code, here :
if (value.equals("2")) {
arrayList.remove(0);
}
you remove the first element of the list. The list has so a size of 2 elements.
The iterator implementation takes into consideration the size of the list to know if it has next elements or not :
public class ArrayList<E> extends AbstractList<E>
...
private class Itr implements Iterator<E> {
public boolean hasNext() {
return cursor != size;
}
}
Since two elements were iterated and that the list has now a size of 2 because you remove one element of it, the iterator considers that it has not next element to iterate on.
If you use an iterator to remove the current element, you have not this side-effect.
Being new to Java, the following code confuses me. I'm trying to do a simple loop based on a list.
List memberships = getMembership(username);
for( Iterator<Integer> single = memberships.iterator(); single.hasNext(); )
{
System.out.println(print_the_current_string_in_list);
}
I have the following questions:
The loop never stops with the above, even though I only have three items in the list. Why is this?
How can I output the current string in the list?
Hopefully your List if of type String and not Integer so it should be
List<String> memberships = getMembership(username);
There are multiple ways to loop over the data for example:
for(String single : memberships) {
System.out.println(single);
}
Another way:
for(int i = 0; i < memberships.size(); i++) {
System.out.println(memberships.get(i));
}
Using the Iterator
for(Iterator<String> iterator = membership.iterator(); iterator.hasNext();) {
System.out.println(iterator.next());
}
Instead of using a for loop you may use an Iterator with a while loop
Iterator<String> iterator = membership.iterator();
while(iterator.hasNext()) {
System.out.println(iterator.next());
}
Try an advanced for loop, like so:
for(String membership : memberships)
System.out.println(membership);
You can use the foreach statement, which uses the iterator that the list has already implemented.
And you should also specify the type of the elements that the list will contain in the List declaration, like this:
List<String> memberships = getMembership(username);
for( String m : memberships )
{
System.out.println(m);
}
You need to actually iterate over the members with next() method from Iterator:
for (Iterator<Integer> single = memberships.iterator (); single.hasNext (); ) {
Integer next = single.next ();
System.out.println (next);
}
Also, you can use the new for each construct:
for (Integer current : memberships)
System.out.println (current);
You haven't iterated through the list.Use next() method.Thats why its going into an infinite loop.
for( Iterator<Integer> single = memberships.iterator(); single.hasNext();{
System.out.println( single.next());
}
I'm trying to iterate throuh a list while already looping through it (nested loops). Consider the code below:
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
for(int i : list) { // ConcurrentModificationException
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
int n = iterator.next();
if(n % i == 0) {
iterator.remove();
}
}
}
The example above results in a ConcurrentModificationException. The condition to remove an element is, of course, just an example.
I'm sure I'm just missing something; but how should I construct a loop that achieves the same thing in Java without throwing an exception?
Obviously modifying list when you iterate over it causing the execption.
You can use another list to maintain the list of elements to be removed and remove them at the end.
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
ArrayList<Integer> del = new ArrayList<Integer>(); // Elements to be deleted
for(int i : list) { // ConcurrentModificationException
Iterator iterator = list.iterator();
while(iterator.hasNext()) {
int n = iterator.next();
if(n % i == 0) {
del.add(n);
}
}
}
list.removeALL(del);
Make the outer iteration iterate over a copy of the list.
for (int i : new ArrayList<>(list)) {
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
int n = iterator.next();
if (n % i == 0) {
iterator.remove();
}
}
}
You are getting ConcurrentModificationException because, while doing for loop you are trying to modify the list.
I am not sure whether following is elegant solution or not, but something like below may work:
Iterator<Integer> iterator = list.iterator();
int i=1;
while (iterator.hasNext()) {
int n = iterator.next();
if (n % i == 0) {
iterator.remove();
}
i++;
}
You cannot remove an item from a list that is being iterated. One option is to add the items that you need to another list. Finally you have list with the items you need. Or you can iterate over the clone of your original list.
i do some thing pretty similar to you. hav e alook at this code .
out:for(int h=0; h<tempAl.size(); h++) {
if(tempAl.get(0).split("\\s")[0].equals("OFF")){
tempAl.remove(0);
h=-1;
continue;
}
if(tempAl.get(h).split("\\s")[0].equals("ON")){
ONTime= tempAl.get(h);
///rest fof the code
}
i think you could also change the index after removing element from the arraylist.
I haven't tried, but either use:
List<Integer> list = new ArrayList<Integer>();
// add some values to it
for(Iterator<Integer> iterator1 = list.iterator(); iterator1.hasNext();) {
int i = iterator1.next();
for(Iterator<Integer> iterator2 = list.iterator(); iterator2.hasNext();){
int n = iterator.next();
if(n % i == 0) {
iterator2.remove();
}
}
}
or if this still throws the ConcurrentModificationException (I'm not sure what happens if you use 2 iterators backed by the same list), then use:
List<Integer> list = new ArrayList<Integer>();
// add some values to it
for(int i : new ArrayList(list)){ // copy list
...
}
foreach java syntax hides an iterator but as hiding it, it is not possible to call remove method on this one.
So I would do:
ArrayList<Integer> list = new ArrayList<Integer>(); // add some values to it
int count = 0;
for(Iterator<Integer> it = list.iterator();it.hasNext();count++){ //increments count++
Integer currentInt = it.next();
if(currentInt % count == 0){
it.remove();
}
}
You can see that the same feature is achieved without the need of a secondary iterator.
You can't iterate through the same list in the same time.
To sum up, a modcount variable is used to detect unexpected change of itself everytime a list is parallely changed or iterated over.
Leading thus to a ConcurrentModificationException.
It appears very often with multithreaded environment and developers must be aware of it.
Furthermore, prefer use for loop instead while loop to iterate over a collection.
Why ?
Because with the while way, you let the iterator object still in scope after the loop whereas with for, it doesn't. A simple ackward call to it.next() would end up with a NoSuchElementException.
It is a best practice to keep ;)
I am using an Iterator to iterate through a collection
and I want to get the current element's index.
How can I do that?
I had the same question and found using a ListIterator worked. Similar to the test above:
List<String> list = Arrays.asList("zero", "one", "two");
ListIterator<String> iter = list.listIterator();
while (iter.hasNext()) {
System.out.println("index: " + iter.nextIndex() + " value: " + iter.next());
}
Make sure you call the nextIndex() before you actually get the next().
Use your own variable and increment it in the loop.
Here's a way to do it using your own variable and keeping it concise:
List<String> list = Arrays.asList("zero", "one", "two");
int i = 0;
for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {
String s = it.next();
System.out.println(i + ": " + s);
}
Output (you guessed it):
0: zero
1: one
2: two
The advantage is that you don't increment your index within the loop (although you need to be careful to only call Iterator#next once per loop - just do it at the top).
You can use ListIterator to do the counting:
final List<String> list = Arrays.asList("zero", "one", "two", "three");
for (final ListIterator<String> it = list.listIterator(); it.hasNext();) {
final String s = it.next();
System.out.println(it.previousIndex() + ": " + s);
}
What kind of collection? If it's an implementation of the List interface then you could just use it.nextIndex() - 1.
Use an int and increment it within your loop.
just do something like this:
ListIterator<String> it = list1.listIterator();
int index = -1;
while (it.hasNext()) {
index++;
String value = it.next();
//At this point the index can be checked for the current element.
}
Use a ListIterator to iterate through the Collection. If the Collection is not a List to start with use Arrays.asList(Collection.toArray()) to turn it into a List first.
All you need to use it the iterator.nextIndex() to return the current index that the iterator is on. This could be a bit easier than using your own counter variable (which still works also).
public static void main(String[] args) {
String[] str1 = {"list item 1", "list item 2", "list item 3", "list item 4"};
List<String> list1 = new ArrayList<String>(Arrays.asList(str1));
ListIterator<String> it = list1.listIterator();
int x = 0;
//The iterator.nextIndex() will return the index for you.
while(it.hasNext()){
int i = it.nextIndex();
System.out.println(it.next() + " is at index" + i);
}
}
This code will go through the list1 list one item at a time and print the item's text, then "is at index" then it will print the index that the iterator found it at. :)
See here.
iterator.nextIndex() would provide index of element that would be returned by subsequent call to next().
Though you already had the answer, thought to add some info.
As you mentioned Collections explicitly, you can't use listIterator to get the index for all types of collections.
List interfaces - ArrayList, LinkedList, Vector and Stack.
Has both iterator() and listIterator()
Set interfaces - HashSet, LinkedHashSet, TreeSet and EnumSet.
Has only iterator()
Map interfaces - HashMap, LinkedHashMap, TreeMap and IdentityHashMap
Has no iterators, but can be iterated using through the keySet() / values() or entrySet() as keySet() and entrySet() returns Set and values() returns Collection.
So its better to use iterators() with continuous increment of a value to get the current index for any collection type.