Puzzler: Nested computeIfAbsent -Java 8
2015-08-06 22:01
507 查看
Puzzler: Nested computeIfAbsent
The Java 8 libraries have a new method on map, computeIfAbsent. This is very useful way to turn your Map into a cache of objects associated with a key.However, there is a combination you might not have considered; what happens if you call computeIfAbsent inside itself.
map.computeIfAbsent(Key.Hello, s -> { map.computeIfAbsent(Key.Hello, t -> 1); return 2; }); enum Key {Hello}
While this might seem like a strange thing to do in simple cases, in more complex code you could do this by accident (as I did this afternoon) So what happens? Well it depends on the collection you are using.
HashMap: {Hello=2} WeakHashMap: {Hello=2} TreeMap: {Hello=2} IdentityHashMap: {Hello=2} EnumMap: {Hello=2} Hashtable: {Hello=2, Hello=1} LinkedHashMap: {Hello=1, Hello=2} ConcurrentSkipListMap: {Hello=1} ConcurrentHashMap:
Note: ConcurrentHashMap never returns. It's locking doesn't appear to be re-entrant.
ConcurrentSkipListMap has the most reasonable result, retaining the first value added. Hello=2 is reasonable for this undefined situation, if confusing as it is the second value not the first. What doesn't make much sense
is to have the unique immutable key appear twice.
Having ConcurrentHashMap deadlock itself is unfortunate but at least its not subtle.
The complete code.
public class A { public static void main(String[] args) { for (Map map : new Map[]{ new HashMap<>(), new WeakHashMap<>(), new TreeMap<>(), new IdentityHashMap<>(), new EnumMap<>(Key.class), new Hashtable<>(), new LinkedHashMap<>(), new ConcurrentSkipListMap<>(), new ConcurrentHashMap<>() }) { System.out.print(map.getClass().getSimpleName() + ": "); map.computeIfAbsent(Key.Hello, s -> { map.computeIfAbsent(Key.Hello, t -> 1); return 2; }); System.out.println(map); } } enum Key {Hello} }
The method compute() has similar results
HashMap: {Hello=null2} WeakHashMap: {Hello=null2} TreeMap: {Hello=null2} IdentityHashMap: {Hello=null2} EnumMap: {Hello=null2} Hashtable: {Hello=null2, Hello=1} LinkedHashMap: {Hello=1, Hello=null2} ConcurrentSkipListMap: {Hello=12} ConcurrentHashMap:
Conclusion
You need to be careful if you nest calls to a map from inside a lambda, or avoid doing so at all. If you have to do this, ConcurrentSkipListMap appears to behave the best.
From:https://dzone.com/articles/java-8-and-jsr-335-lambda-expressions-12
相关文章推荐
- JAVA技术交流群
- Struts2知多少(2) Struts2 是什么
- Java机试题目_怎样截取字符串
- 关于eclipse生成web工程的时候没有web.xml文件的解决方案
- Java汉字转换为拼音
- Spring的Ioc(控制反转)和DI(依赖注入)
- 理解Java的IO流 2015年8月6日 21:30:38
- Java实现算法之--二分查找法
- Win7环境下用MyEclipse搭建Hbase开发环境
- Java实现算法之--求子数组和的最大值
- 用dom4j解析xml 报java.lang.NoClassDefFoundError:org/jaxen/JaxenException
- 【Java】Java处理double相加的结果异常
- JDK动态代理机制
- Spring注解详解
- myeclipse 提示No Default Proposals 或 no completions available 的解决方法
- 解决Opentaps/OFBiz在Eclipse启动时"Could not load VFS configuration"的问题
- 解决ofbiz在myeclipse中调试运行时报错:Can't find bundle for base name cache
- java设计模式(9) - 适配器模式
- java中进行二进制,八进制,十六进制,十进制间进行相互转换
- java设计模式(8) - 享元模式