Skip to content

Instantly share code, notes, and snippets.

@tomwhoiscontrary
Created May 19, 2017 17:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomwhoiscontrary/7a1d9f61f4ecc8fcb7b81e86ff276a82 to your computer and use it in GitHub Desktop.
Save tomwhoiscontrary/7a1d9f61f4ecc8fcb7b81e86ff276a82 to your computer and use it in GitHub Desktop.
Reentrant use of HashMap::computeIfAbsent leaves the map in an inconsistent state
import java.util.HashMap;
import java.util.Map;
public class DoesNotCompute {
public static void main(String[] args) {
System.out.println(System.getProperty("java.version"));
Map<String, Integer> map = new HashMap<>();
map.computeIfAbsent("spud", s -> calculate(s, map));
System.out.println("map = " + map);
System.out.println("map.size() = " + map.size());
System.out.println("new HashMap(map).size() = " + new HashMap<>(map).size());
}
private static Integer calculate(String key, Map<String, Integer> map) {
if (key.isEmpty()) {
return 0;
} else {
String left = key.substring(0, key.length() - 1);
String right = key.substring(1);
return 1
+ map.computeIfAbsent(left, s -> calculate(s, map))
+ map.computeIfAbsent(right, s -> calculate(s, map));
}
}
}
1.8.0_131
map = {p=1, =0, s=1, d=1, u=1, pu=3, spud=15, sp=3, pud=7, ud=3}
map.size() = 12
new HashMap(map).size() = 10
@henry701
Copy link

Abysmally, this also happens with a ConcurrentHashMap, and potentially puts the thread in an infinite loop.

@tomwhoiscontrary
Copy link
Author

At least now it crashes:

11
Exception in thread "main" java.util.ConcurrentModificationException
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1134)
	at DoesNotCompute.calculate(DoesNotCompute.java:24)
	at DoesNotCompute.lambda$calculate$1(DoesNotCompute.java:24)
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1133)
	at DoesNotCompute.calculate(DoesNotCompute.java:24)
	at DoesNotCompute.lambda$calculate$1(DoesNotCompute.java:24)
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1133)
	at DoesNotCompute.calculate(DoesNotCompute.java:24)
	at DoesNotCompute.lambda$main$0(DoesNotCompute.java:10)
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1133)
	at DoesNotCompute.main(DoesNotCompute.java:10)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment