0

suppose you have a HashMap m and there is already a key value pair <"key1", object> inside.

can you do the following?

m.put("newkey", m.remove("key1"))

will you get a ConcurrentModificationException?

Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
Junchen Liu
  • 5,435
  • 10
  • 51
  • 62
  • 4
    just try it before asking ;-) – Matteo Nov 28 '11 at 14:37
  • Why is this being closed? I think the question is clear...? – Lukas Eder Nov 28 '11 at 14:37
  • @Matteo in the world of software programming, there is try it once or twice doesn't reveal the true answer, what you seen is a fragment of our code. problems somethimes can be difficult to reproduce, especially threading issue. even after try it, I still want to know why it worked, or why it did not work, personally I think give people option to close post , is very bad practice. becasue there are too many people here, way smart then the average – Junchen Liu Nov 28 '11 at 15:19
  • @shanyangqu First of all, I did not ask to close this post. Instead, I saw that the question was trivial, and there was a good answer to that (which I voted for). As you might see from my questions, I AM a software engineer, and I write programs. In my experience, I saw that software systems using a single thread without any I/O, tend to be deterministic. And the code you posted only uses a single thread and does not perform any I/O. So, it is likely to be deterministic. Hence I suggest to run it (alone, without the rest of your app), debug it, and understand how simple was your question. – Matteo Nov 28 '11 at 18:34
  • @Matteo: you are of course right in this part: "And the code you posted only uses a single thread and does not perform any I/O. So, it is likely to be deterministic. ". But given the question, you wrongly assume that the asker would be in possession of this piece of information. Trying it would not reveal the reason *why* it is valid code anyway, or the hint that, for readability, you *should* use two lines instead of just one (with a temporary variable called "removedValue" for instance). – Maarten Bodewes Nov 29 '11 at 23:31

4 Answers4

7

You can do that as long as it's not in the body of a loop that is iterating over the hashMap entries. The way that will work is that the remove operation will execute and complete before the put operation so it's semantically equivalent to doing it in 2 lines.

Chris
  • 22,923
  • 4
  • 56
  • 50
  • 1
    Because if the loop is iterating over the map you can't modify the underlying map without triggering the concurrentModificationException since you may be inserting a new row that shows up in the map before your current place in the iterator (for instance). – Chris Nov 28 '11 at 14:39
  • @shanyangqu You could do that in a loop unless you use an iterator over that hashmap (useing a foreach loop etc.). Those iterators check whether there were modifications not made through them and throw the `ConcurrentModificationException`. – Thomas Nov 28 '11 at 14:41
  • @Thomas, I believe the Iterator way is the way to go if you intend to modify or remove entries from the Map. See http://stackoverflow.com/questions/1066589/java-iterate-through-hashmap – mjs Nov 28 '11 at 14:54
  • Note: an `Iterator` for `HashMap` will trigger a concurrent modification exception even if you do remove or put in the same thread. If you use `ConcurrentHashMap` it will not produce a `ConcurrentModificationException` as its designed not to. – Peter Lawrey Nov 28 '11 at 14:55
  • @Hamidam, but not if you want to change keys, which requires the use of a `put()`. – Peter Lawrey Nov 28 '11 at 14:56
  • thanks, I know why it can't be in a loop, but I have a problem to reproduce it, it seems in a loop, it could work sometimes, if its a bad practice, it doesn't fail everything ,why? – Junchen Liu Nov 28 '11 at 14:59
  • @shanyangqu As stated, it depends on what you do in the loop. Are you working with iterators? Could you post the code of that loop? – Thomas Nov 28 '11 at 15:21
  • for(Map.Entry entry : m.entrySet()){ if(entry.getValue() = "key1") m.put("newkey", m.remove("key1"))} – Junchen Liu Nov 28 '11 at 15:25
1

Just tested it for you.

Map<String, Object> map = new HashMap<String, Object>();        
map.put("k1", Integer.valueOf(999));        
map.put("k2", map.remove("k1"));
System.out.println(map.get("k2"));

Prints:

999

No exception (ConcurrentModificationException).

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
0

Since m.remove returns the object previously associated with that key, you should be able to use that object however you like. So no, I don't believe you should get an exception.

Gerard
  • 4,818
  • 5
  • 51
  • 80
0

They are actually not fired simultaneously. The remove is called first, and done with, then the get is called, so I see no reason as to why there would be an exception.

See this if you need to modify when looping: Iterate through a HashMap

Community
  • 1
  • 1
mjs
  • 21,431
  • 31
  • 118
  • 200