1

I converted a java hashmap to scala map. And I want to delete the element in this map while iterating. But I got this error:java.lang.UnsupportedOperationException. This is my code. And when compiling there was no error.

    var smap = mapAsScalaMap(instCreatorConfig.getMap())
    var it:Iterator[(String,List[List[String]])]=smap.iterator
    while (it.hasNext()) {
      var t= it.next()
      var k= t._1
      var v= t._2
      println("Key :"+k)
      println("Value :"+v)
      it.remove()
}

And if the code is like this:

for((k,v) <-smap){
    ...
    ...
    ...
    smap.remove(k)
   }

I got the java.util.ConcurrentModificationException. Why? And what's the right solution?

3
  • 2
    Unrelated to the problem, but you probably should't call next like that - The first one gets the key of the first tuple in the iterator, the second one the value of the second tuple. You probably want the key and the value of the first tuple. Commented Sep 27, 2015 at 10:01
  • yeah, I didn't notice. Thank you. I was just thinking about the removing part. Commented Sep 27, 2015 at 10:14
  • Ok, I will have a try. Commented Sep 27, 2015 at 10:22

1 Answer 1

2

Digging into what mapAsScalaMap is actually doing, it returns a wrapper of type JMapWrapper (source code here), which provides a (Scala) Iterator (that extends AbstractIterator), providing implementations of next and hasNext.

Now, scala's Iterator trait does not include a remove() method, so what is happening at the line it.remove(), is that the Scala compiler looks for an implicit conversion that would convert the Scala Iterator into something that has a remove() method - and finds scala.collection.JavaConversions.asJavaIterator, which you almost surely have available in scope because you likely just bulk imported all the java conversion functions via import scala.collection.JavaConversions._ (or similar).

This method, asJavaIterator, returns an IteratorWrapper (defined in the same source file) which specifically defines the remove() method as throwing an UnsupportedOperationException.

Moving on to the updated part of the question, using smap.remove(k), this is handled by the wrapping JMapWrapperLike by passing the call on to the underlying java map, which will typically throw a ConcurrentModificationException if you try to remove an entry from the map, then call hasNext() on an associated (Java) Iterator, which you have, wrapped in the IteratorWrapper called it.

As to how to fix all of this, first I would need to know why you need to remove the entry in the first place - what are you trying to achieve here?

Sign up to request clarification or add additional context in comments.

4 Comments

yeah, it seems you are right. I just checked the scala Iterator and it has not the remove method. I just move from java so I thought it may has the same feature as java. But still is the question. How to remove the element without causing the "java.util.ConcurrentModificationException"? Thank you.
@deathlee As per the edit of my answer - why do you want to remove the entry anyway? What reason do you have for doing that?
I want to remove because the heap blow up. I need to store a large java hashmap in the first place and process the data in the map one by one. And I don't need the data after processing. So I just want to remove the element after I processed the data point and let GC collect them so I will have free memory.
@deathlee The heap is exceeded? I would have thought that would happen when loading the original Java Map, not later after creating just a couple of wrapper classes, and a couple of quickly-GCed, loop-scoped vars - it should be way too late to save the heap at that point.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.