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] [Comment Edited] (COLLECTIONS-663) Unexpected ConcurrentModificationException when altering Collection of a MultiValuedMap
Date Sun, 05 Nov 2017 13:21:00 GMT

    [ https://issues.apache.org/jira/browse/COLLECTIONS-663?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16239524#comment-16239524
] 

Christophe Schmaltz edited comment on COLLECTIONS-663 at 11/5/17 1:20 PM:
--------------------------------------------------------------------------

Thank you for your response.

I once used the {{MapIterator}}, sadly I found out that it doesn't support what I try to achieve:
{code}	@Test
	public void testWhatINeedToWork() {
		// ArrayListValuedHashMap<Integer, Integer> multiMap = new ArrayListValuedHashMap<>();
		MultiValuedMap<Integer, Integer> multiMap = new HashSetValuedHashMap<>();

		multiMap.put(1, 10);
		multiMap.put(1, 11);
		multiMap.put(2, 20);
		Iterator<Integer> it = multiMap.mapIterator();
		for (MapIterator<Integer, Integer> iterator = multiMap.mapIterator(); iterator.hasNext();)
{
			iterator.next();
			Integer value = iterator.getValue();
			if ((value % 2) == 0) {
				// Integer is immutable, we need to replace using setValue(.)
				iterator.setValue(value * 2);
			}
		}
	}{code}
My issue was that {{MapIterator.setValue(.)}} is not supported.

(My current workaround is storing the elements I need to change in a list, and pushing them
back in the map afterwards)

I understand the difficulty in implementing it for {{HashSetValuedHashMap}} though, as the
{{HashSet.iterator}} doesn't support it either (sadly, that's what I need).
I observed that {{ArrayListValuedHashMap}} doesn't support {{setValue(.)}} either (should
be possible, as {{ArrayList.listIterator}} has this feature.


was (Author: chris333):
Than you for your response.

I once used the {{MapIterator}}, sadly I found out that it doesn't support what I try to achieve:
{code}	@Test
	public void testWhatINeedToWork() {
		// ArrayListValuedHashMap<Integer, Integer> multiMap = new ArrayListValuedHashMap<>();
		MultiValuedMap<Integer, Integer> multiMap = new HashSetValuedHashMap<>();

		multiMap.put(1, 10);
		multiMap.put(1, 11);
		multiMap.put(2, 20);
		Iterator<Integer> it = multiMap.mapIterator();
		for (MapIterator<Integer, Integer> iterator = multiMap.mapIterator(); iterator.hasNext();)
{
			iterator.next();
			Integer value = iterator.getValue();
			if ((value % 2) == 0) {
				// Integer is immutable, we need to replace using setValue(.)
				iterator.setValue(value * 2);
			}
		}
	}{code}
My issue was that {{MapIterator.setValue(.)}} is not supported.

(My current workaround is storing the elements I need to change in a list, and pushing them
back in the map afterwards)

I understand the difficulty in implementing it for {{HashSetValuedHashMap}} though, as the
{{HashSet.iterator}} doesn't support it either (sadly, that's what I need).
I observed that {{ArrayListValuedHashMap}} doesn't support {{setValue(.)}} either (should
be possible, as {{ArrayList.listIterator}} has this feature.

> 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
>            Assignee: Bruno P. Kinoshita
>            Priority: Trivial
>
> 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