Stack<String> ST = new Stack<String>();
ST.add("one");
ST.add("two");
ST.add("three");
ST.add("four");
ST.addAll(ST.subList(0,2));
System.out.println(ST);
Following Simple Code give java.util.ConcurrentModificationException.I not able to figure it out what is the reason behind for this exception?
List.subList returns a view into the container, not a copy.
From the documentation
The semantics of the list returned by this method become undefined if
the backing list (i.e., this list) is structurally modified in any way
other than via the returned list. (Structural modifications are those
that change the size of this list, or otherwise perturb it in such a
fashion that iterations in progress may yield incorrect results.)
So when you call addAll, it modifies the underlying container and changes its size, invalidating the sublist. But it's still trying to iterate over the sublist to continue adding things.
The documentation for the subList method says:
The semantics of the List returned by this method become undefined if the backing list (i.e., this List) is structurally modified in any way other than via the returned List. (Structural modifications are those that change the size of the List, or otherwise perturb it in such a fashion that iterations in progress may yield incorrect results.)
In other words, you're not allowed to change the real list while you're accessing the sublist.
When you call
ST.addAll(ST.subList(0,2));
you're causing addAll to traverse the sublist and modify the real list (ST) at the same time. addAll will take the first element from the sublist and append it to ST, which is a structural modification that invalidates any sublists based on ST. Then addAll will try to take the second element from the sublist, but the sublist is now invalid because of the change that was just made to ST, so it throws the exception.
The problem happens in here:
ST.addAll(ST.subList(0,2));
The problem is that under the hood the following things are happening:
The ST.subList(0,2) call creates a wrapper for the original list.
The ST.addAll call creates an Iterator for the sublist which is actually a wrapper for a ListIterator for the original list.
Then, while iterating the sublist (and hence the list), it pushes the elements it finds back onto the original list.
The last is a concurrent modification.
Note that this is inherent, not just an implementation detail. The subList method returns a view of the original List. Therefore your statement is inherently iterating and modifying the same (underlying) list concurrently.
Related
Scenario 1:::
So I have list of params, which is passed to 2 methods which calls web service and gets the data. These to methods just do stream.filter.collect on the list of params to get the needed parameter for rest call.
Now I have made the 2 calls parallel using CompletableFutures.
Can this throw ConcurrentModifcation exception?
Scenario 2:::
Similar setup as above , just that now one method changes the list of params and adds some objects to it. I know this is throwing Concurrent Modification exp. Should I just make list as copyonWriteArraylist or create new list with deep copy to avoid any further problems.
Scenario #1: Probably not, but your description is too vague to be sure.
Scenario #2: Most absolutely.
The only thing you need for CoModEx to occur is that the list is changed in any way. Be it add, addAll, clear, remove, retainAll, or any other method on List that has the effect of changing the list itself. Even fetching a sublist and changing THAT (as changes to sublist are visible from the 'outer' list that the sublist was created from).
CoModEx, despite the use of the word 'concurrent', has zip squat to do with threads. In fact, messing with a list from two threads simultaneously is one of the few ways you can break things (methods no longer do what their javadoc says they should) without causing a ConcurrentModificationException (will depend on how the race condition goes).
Here is a trivial way to get a CoModEx:
var list = new ArrayList<String>();
list.add("Hello");
list.add("World");
for (String item : list) if (item.equals("Hello")) list.remove(item);
That will throw it. Every time. CoModEx is thrown by iterators (and the for (x:y) constructor will implicitly create iterators, as does x.stream()..., which creates a spliterator, which also does this) when the underlying data structure was changed in any way that is not directly done by the (spl)iterator itself. For example, this is the one way you get to remove things from your own list using an iterator that does not result in CoModEx:
var it = list.iterator();
while (it.hasNext()) {
if (it.next().startsWith("Hello")) it.remove();
}
Note I'm calling iterator's remove, not list's remove, which would have caused CoModEx: That would change the underlying list (and not via the iterator directly), therefore any operation on an iterator created before the modification will throw CoModEx.
So, this is the flow:
You create an iterator from list, by entering for (String item : list).
That iterator's hasNext() is invoked to check if the for loop should be entered. It returns true
That iterator's next() is invoked for the first loop; Hello is returned.
Due to the code inside the for loop, list.remove("Hello") is invoked. This 'invalidates' all iterators that were created by this list so far.
the for loop loops, and invokes hasNext() to check if it should loop again.
hasNext realizes that it is invalid, and throws CoModEx.
ArrayList does this by having a counter which is incremented every time anything changes, and all iterators remember the value of the counter when created, and check that the list's counter value is equal to their own. If not, they throw CoModEx. Other list impls can use different mechanisms if they desire. Some go out of their way to actually allow this (such as CopyOnWriteArrayList, which explicitly details how it DOES let you modify itself during iteration).
If multiple threads are involved, all bets are off - those counter writes are not synchronized and therefore may or may not be visible by the threads involved. Don't access the same list from different threads unless you really know what you are doing.
I have a LinkedList. Suppose that I'm inserting an element at the end and I want to save the position where was it inserted, so that I can call a function on an element next to it, whatever manages to get into this collection later. Is it possible with Java iterators? Many thanks.
Just to recollect, I'm not interested in reverse iteration. The application will be multithreaded, hence the weird requirement.
You can call List#listIterator(int index) with index = size() -1 to get an iterator to the current last element of the list. See documentation: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/List.html
However, you are going to be stuck from there.
Whether the List implementation you are using isn't thread-safe, which is the case for LinkedList, ArrayList and most others, and any attempt to use the iterator after the list has been structurally modified is going to result in a ConcurrentModificationException being thrown.
A list is structurally modified when its size changes, i.e. on additions and removals.
Or the List implementation you are using is thread-safe, in which case you have no guaranty that the iterator will have access to the elements added to the list after the creation of the iterator.
For example, it wouldn't be the case with CopyOnWriteArrayList, for which the iterator iterates through data as it was at creation (like a snapshot).
You must find an implementation of List that clearly describe this behavior and explicitly say it in its documentation. As far as I know, there doesn't exist any that allow it, at least in the standard library.
LinkedList is a data structure, in which each element is coupled with a link to its next element.
So, in theory, this data structure is made for freely iterating through a list, in whichever direction, while performing whatever operations (except, maybe, deleting the element you're currently at).
However, in application, this isn't true. Returning an Iterator from a LinkedList is subject to the general Iterator rules (i.e. no modifying while iterating), and even creating a ListIterator, an improved Iterator, which allows modifying the next/previous element of the iterator, and let's you go forward/backward dynamically, still has severe limitations:
You can't delete elements from the beginning of the list if you're not currently there, and neither can you add elements to the end of the list, unless you're currently there.
So, is there a way to iterate freely through a LinkedList while performing whatever modifications to the list? And if not, why isn't there one? Shouldn't it be one of the main goals of this data structure to realize it?
The choice to make all Iterators failfast was a design decision, just that and nothing more.
Nothing stops you to take the code and starting from that, build a NotSoFailFastIterator for yourself if you think you can use it. However I think you'll quickly revert from using it once yoy see its behaviour and its results in usage scenarios where there's really lots of concurrent activity going on on the underlying List of your iterator.
This behavior is not specific to LinkedLists. When you iterate over a List (any List) with a ListIterator, you can only make structural changes (adding or removing elements) in the current position of the iterator. Otherwise, continuing to use the iterator after a structural change of the List may yield unexpected results.
For adding elements to the start or end of the LinkedList, you have addFirst and addLast methods. You don't have to iterate over the List in order to do that.
A ListIterator instance maintains a state that allows it to locate the next and previous elements as well as support other operations (remove the current element, add an element at the current position). If you make a structural change to a List not via the ListIterator, the state of the iterator may become invalid, leading to unexpected results. Therefore all structural changes must be made via the ListIterator.
I guess that the LinkedList class could supply an implementation of a more complex iterator that supports operations such as addFirst and addLast. I'm not sure how useful that would have been, and whether it would justify the added complexity.
If you want to iterate freely use array or list. Linked lists are meant to be traversed and access the data useful in dynamic allocation of the memory to the data.
When you have a linked list datastructure, you can add or remove at a particular node, when your cursor is pointing to the right node where you want to add or remove.
Inserts the specified element into the list (optional operation). The
element is inserted immediately before the element that would be
returned by next(), if any, and after the element that would be
returned by previous(), if any. The new element is inserted before
the implicit cursor: a subsequent call to next would be unaffected,
and a subsequent call to previous would return the new element. (This
call increases by one the value that would be returned by a call to
nextIndex or previousIndex.)
ListIterator
Instead if its a array structure, then you access by index , and it is possible to add or remove at a particular index limited , by the length of the array. ArrayList does that.
If I obtain a subList from a List (or obtain an Iterator or ListIterator from a List) and after that do a non-structural modification (set(index, E)) - I am guaranteed to get no ConcurrentModificationException. But is there guarantee that my subList and Iterator/ListIterator see those changes?
Experimentally, when I make changes in the same thread (main()), subList and Iterator/ListIterator see those changes. But if I make changes from other threads? My guess - seeing chages guaranteed if made from synchronized method/block in another thread and not guaranteed otherwise (from non-synchronized code in other thread)
For Map collection views API is clear - if I obtain a collection view and then change original map (even replace) then collection view may or may not represent those changes, and no exception is thrown.
P.S. For subList - seeing non-structtural changes is guaranteed. It follows from API:
The returned list is backed by this list, so non-structural changes in
the returned list are reflected in this list, and vice-versa.
But API has no answer for Iterator and ListIterator.
I'm running into this problem in a unit test.
After executing:
List<Card> cleanCards = cards.subList(0, cards.size() - difference);
the following assert gives me a ConcurrentModificationException:
assertEquals(limit, cleanCards.size());
Error description
java.util.ConcurrentModificationException
at java.util.ArrayList$SubList.size(ArrayList.java:1057)
To my knowledge, the 'size()' method does not make structural changes to the list. Am I missing something here?
Most likely the original list is being modified between the sub-list creation and its use. subList does not create an independent new list, but rather a view of a section of the original list, and as the specs say
The semantics of the list returned by this method become undefined if
the backing list (i.e., this list) is structurally modified in any way
other than via the returned list. (Structural modifications are those
that change the size of this list, or otherwise perturb it in such a
fashion that iterations in progress may yield incorrect results.)
and in your case, the "undefined" behaviour seems to result in an exception being thrown, also known as fail-fast behaviour. I reckon an easy solution would be to change the first line above to
List<Card> cleanCards = new ArrayList<>(cards.subList(0, cards.size() - difference));
which copies the sub-list to a completely new list independent of the original.