Win a copy of The Business Blockchain this week in the Cloud forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Removing ArrayList element while iterating

 
francisco de feudis
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello guys, I have two questions about this piece of code:


    List<Integer> list = new ArrayList<Integer>();
    list.add(new Integer(0));
    list.add(new Integer(1));
    list.add(new Integer(2));
    list.add(new Integer(3));
    System.out.println(list);
    for (Integer i : list) {
          System.out.println(i);
      if (i >= 2) {
            System.out.println("remove " + i);
            list.remove(i);
       // list.remove(0); // line 1
      }
    }
    System.out.println(list);


1) why Integer 3 hasn't been removed at the end of the iteration?
2) why if I decomment line 1 I get a RuntimeException ? I mean: what is the rule on the basis of we can remove while iterating?
We can remove element that hasn't been indexed by the iterator yet, but not the previous one of the current element?

Thank you everybody
 
praveen kumaar
Ranch Hand
Posts: 242
4
Chrome Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
francisco de feudis wrote:1) why Integer 3 hasn't been removed at the end of the iteration?


see,if you iterate the list using a for each loop then internally it uses an iterator(which is inaccessible) for the same task and the iterator returned by a list is a fail-fast.if you tried to modify the list like you have done "list.remove(i)" produces an indeterministic behaviour.
francisco de feudis wrote:2) why if I decomment line 1 I get a RuntimeException ? I mean: what is the rule on the basis of we can remove while iterating?

now here you will get a ConcurrentModificationException,because the statement "list.remove(i)" will structurally modifies the list after the iterator was created and adding a line list.remove(0) will make the iterator to know the fact that the original list is modified in previous line so will throw a such exception.

Note:the list is modified at line-list.remove(i) though it doesnot throw an exception there because the iterator doesnot knows about it.the next line(in your code) make it sure about the same.i.e.,when ever you will try to access a iterator(ListIterator) after some modication or filtering of list it will throw ConcurrentModificationException.

Read this-for-each loop -by oracle , read about ListIterator here.
also please read the List API for better understanding.

Hope it helps!

Kind Regards,
Praveen.
 
praveen kumaar
Ranch Hand
Posts: 242
4
Chrome Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
francisco de feudis wrote:We can remove element that hasn't been indexed by the iterator yet, but not the previous one of the current element?
no this is incorrect,try replacing "i" with "0" in your code at line-"list.remove(i)".

[Edit=for previous post]-the integer 3 will not get removed because iterator will fail after the line "list.remove(i)" in your code.

Kind regards,
Praveen.
 
francisco de feudis
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Praveen, thank you very much for the reply.

I've read the docs you posted, I'm still missing something and I know that it is my fault, please be patient.

I was thinking about the remove following by another remove.

If I can execute



why I can't do



Indeed list.remove(i) is executed two or more times, because it's placed in the for loop.

Shouldn't list.remove throw exception even in the first code snippet above, at the second loop?

I think that would be better if java always throw exception when list.remove method is called in for-loops, and let its use instead only outside loops.

What I'm missing?

Thanks again.
 
praveen kumaar
Ranch Hand
Posts: 242
4
Chrome Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
francisco de feudis wrote:what is the rule on the basis of we can remove while iterating?

Despite of saying it a rule i would better say the best way or a only safe way to remove an element from list is by using Iterator.remove method.here below is the implementation:


Kind Regards,
Praveen.
 
praveen kumaar
Ranch Hand
Posts: 242
4
Chrome Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
francisco de feudis wrote:Indeed list.remove(i) is executed two or more times, because it's placed in the for loop.


see the code:

the above code will throw an Exception at second iteration.
consider another code-


here it will not complaint because "i" is a reference to the current element in a list iterator and "i" has been referenced before modification i.e.,removal.if you will use another element like i+1,i-1,0....in method argument then for removing such element in a list it needs an iterator to get to that position or for traversing from current reference to required reference.just because this time it needs iterator,so here it makes sure to iterator that some modification has been done in previous steps so will throw an exception.

Hope it helps!

Kind regards,
Praveen.
 
Henry Wong
author
Marshal
Pie
Posts: 22085
88
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
francisco de feudis wrote:
Indeed list.remove(i) is executed two or more times, because it's placed in the for loop.

Shouldn't list.remove throw exception even in the first code snippet above, at the second loop?

I think that would be better if java always throw exception when list.remove method is called in for-loops, and let its use instead only outside loops.

What I'm missing?


The JavaDocs actually mentions this...

Java 8 ArrayList JavaDoc wrote:Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.


Henry
 
praveen kumaar
Ranch Hand
Posts: 242
4
Chrome Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
francisco de feudis wrote:If I can execute


....Shouldn't list.remove throw exception even in the first code snippet above, at the second loop?


Nope,it would fail at second iteration and throw an exception.Try it!

Kind Regards,
Praveen.
 
francisco de feudis
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Ok, thank you again, maybe now I am
Let me explain by my words, please correct me if I'm wrong: once you created an iterator over a List, you can access any element of the list but you cannot modify them (because this would need another iterator).
Just you can work on the current iterator element where there are no conflict.


Please really last question:



It works.



But why this doesn't?
 
praveen kumaar
Ranch Hand
Posts: 242
4
Chrome Java Oracle
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator


Hope it helps now!

Kind regards,
Praveen.
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic