commons-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Christophe Schmaltz (JIRA)" <j...@apache.org>
Subject [jira] [Updated] (COLLECTIONS-663) Unexpected ConcurrentModificationException when altering Collection of a MultiValuedMap
Date Sat, 04 Nov 2017 18:12:00 GMT

     [ https://issues.apache.org/jira/browse/COLLECTIONS-663?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Christophe Schmaltz updated COLLECTIONS-663:
--------------------------------------------
    Description: 
Testcase:
{code}	@Test
	public void test() {
		MultiValuedMap<Integer, Integer> multiMap = new HashSetValuedHashMap<>();
		multiMap.put(1, 10);
		multiMap.put(2, 20);
		for (Collection<Integer> innerCollection : multiMap.asMap().values()) {
			for (Iterator<Integer> iterator = innerCollection.iterator(); iterator.hasNext();)
{
				Integer i = iterator.next();
				iterator.remove(); // only the innerCollection is altered
			}
			// innerCollection.add(6); // adding stuff back should also work...
		}
	}{code}
This test unexpectedly throws a ConcurrentModificationException.
The issue is that when calling {{iterator.remove()}} the {{AbstractMultiValuedMap.ValuesIterator}}
detects that the Collection is empty and calls {{AbstractMultiValuedMap.this.remove(key);}}.

It may be better if the iterator of the inner collection had a reference on the iterator if
the outer map and called {{containerIterator.remove()}} instead.
*Note:* this solution would again present issues if the user tries to add new elements in
this now empty collection (which was removed from the parent).


In the current state, it is quite unclear why an exception is thrown, without debugging the
code. 


  was:
Testcase:
{code}	@Test
	public void test() {
		MultiValuedMap<Integer, Integer> multiMap = new HashSetValuedHashMap<>();
		multiMap.put(1, 10);
		multiMap.put(2, 20);
		for (Collection<Integer> innerCollection : multiMap.asMap().values()) {
			for (Iterator<Integer> iterator = innerCollection.iterator(); iterator.hasNext();)
{
				Integer i = iterator.next();
				iterator.remove(); // only the innerCollection is altered
			}
		}
	}{code}
This test unexpectedly throws a ConcurrentModificationException.
The issue is that when calling {{iterator.remove()}} the {{AbstractMultiValuedMap.ValuesIterator}}
detects that the Collection is empty and calls {{AbstractMultiValuedMap.this.remove(key);}}.

It may be better if the iterator of the inner collection had a reference on the iterator if
the outer map and called {{containerIterator.remove()}} instead.
*Note:* this solution would again present issues if the user tries to add new elements in
this now empty collection (which was removed from the parent).


In the current state, it is quite unclear why an exception is thrown, without debugging the
code. 



> Unexpected ConcurrentModificationException when altering Collection of a MultiValuedMap
> ---------------------------------------------------------------------------------------
>
>                 Key: COLLECTIONS-663
>                 URL: https://issues.apache.org/jira/browse/COLLECTIONS-663
>             Project: Commons Collections
>          Issue Type: Bug
>            Reporter: Christophe Schmaltz
>
> Testcase:
> {code}	@Test
> 	public void test() {
> 		MultiValuedMap<Integer, Integer> multiMap = new HashSetValuedHashMap<>();
> 		multiMap.put(1, 10);
> 		multiMap.put(2, 20);
> 		for (Collection<Integer> innerCollection : multiMap.asMap().values()) {
> 			for (Iterator<Integer> iterator = innerCollection.iterator(); iterator.hasNext();)
{
> 				Integer i = iterator.next();
> 				iterator.remove(); // only the innerCollection is altered
> 			}
> 			// innerCollection.add(6); // adding stuff back should also work...
> 		}
> 	}{code}
> This test unexpectedly throws a ConcurrentModificationException.
> The issue is that when calling {{iterator.remove()}} the {{AbstractMultiValuedMap.ValuesIterator}}
detects that the Collection is empty and calls {{AbstractMultiValuedMap.this.remove(key);}}.
> It may be better if the iterator of the inner collection had a reference on the iterator
if the outer map and called {{containerIterator.remove()}} instead.
> *Note:* this solution would again present issues if the user tries to add new elements
in this now empty collection (which was removed from the parent).
> In the current state, it is quite unclear why an exception is thrown, without debugging
the code. 



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Mime
View raw message