Java8使用Map的computeIfAbsent方法构建本地缓存
一、概念及使用介绍
在JAVA8的Map接口中,增加了一个方法computeIfAbsent,此方法签名如下:
- public V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
Map接口的实现类如HashMap,ConcurrentHashMap,HashTable等继承了此方法,通过此方法可以构建JAVA本地缓存,降低程序的计算量,程序的复杂度,使代码简洁,易懂。
此方法首先判断缓存MAP中是否存在指定key的值,如果不存在,会自动调用mappingFunction(key)计算key的value,然后将key = value放入到缓存Map,java8会使用thread-safe的方式从cache中存取记录。
如果mappingFunction(key)返回的值为null或抛出异常,则不会有记录存入map
二、代码样例
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Map;
- import java.util.concurrent.ConcurrentHashMap;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- import java.util.concurrent.TimeUnit;
- public class Main {
- static Map<Integer, Integer> cache = new ConcurrentHashMap<>();
- public static void main(String[] args) throws InterruptedException {
- cache.put(0, 0);
- cache.put(1, 1);
- // 普通方式
- System.out.println("Fibonacci(7) = " fibonacci(7));
- // 采用java7的同步线程方式及java8的本地缓存的方式
- System.out.println("FibonacciJava8(7) = " fibonacciJava8(7));
- System.out.println("FibonacciJava7(7) = " fibonacciJava7(7));
- // 构建多值Map样例代码
- Map<String, HashSet<String>> map1 = new HashMap<>();
- map1.computeIfAbsent("fruits", k -> genValue(k)).add("apple");
- map1.computeIfAbsent("fruits", k -> genValue(k)).add("orange");
- map1.computeIfAbsent("fruits", k -> genValue(k)).add("pear");
- map1.computeIfAbsent("fruits", k -> genValue(k)).add("banana");
- map1.computeIfAbsent("fruits", k -> genValue(k)).add("water");
- System.out.println(map1);
- //测试多线程并发处理,是否同步操作
- Map<String, String> map2 = new ConcurrentHashMap<>();
- ExecutorService exec = Executors.newCachedThreadPool();
- for (int i = 0; i < 5; i ) {
- exec.execute(() -> {
- map2.computeIfAbsent("name", k -> genValue2(k));
- map2.computeIfAbsent("addr", k -> genValue2(k));
- map2.computeIfAbsent("email", k -> genValue2(k));
- map2.computeIfAbsent("mobile", k -> genValue2(k));
- });
- }
- exec.shutdown();
- exec.awaitTermination(1, TimeUnit.SECONDS);
- System.out.println(map2);
- }
- static HashSet<String> genValue(String str) {
- return new HashSet<String>();
- }
- static String genValue2(String str) {
- System.out.println("===");
- return str "2";
- }
- /**
- * 普通的实现方式 普通方式使用大量的计算,存在性能问题. 并且计算量随着n的增加呈指数级增加,需要用到一些缓存策略,并且是线程安全的.
- *
- * @param n
- * @return
- */
- static int fibonacci(int n) {
- if (n == 0 || n == 1)
- return n;
- System.out.println("calculating Fibonacci(" n ")");
- return fibonacci(n - 2) fibonacci(n - 1);
- }
- /**
- * 采用java8的本地缓存方式 如果缓存MAP中不存在指定key的值,会自动调用mappingFunction(key)计算key的value
- * 然后将key = value放入到缓存Map,java8会使用thread-safe的方式从cache中存取记录
- *
- * @param n
- * @return
- */
- static int fibonacciJava8(int n) {
- return cache.computeIfAbsent(n, (key) -> {
- System.out.println("calculating FibonacciJava8 " n);
- return fibonacciJava8(n - 2) fibonacciJava8(n - 1);
- });
- }
- /**
- * 在java7中的实现方式
- * 在java7中,通过synchronized进行线程同步,检查缓存是否存在key对应的值,如果不存在才进行计算并放入缓存中
- * 为了更好的性能,需要使用 double-checked locking,那样代码会更复杂
- *
- * @param n
- * @return
- */
- static int fibonacciJava7(int n) {
- if (n == 0 || n == 1)
- return n;
- Integer result = cache.get(n);
- if (result == null) {
- synchronized (cache) {
- result = cache.get(n);
- if (result == null) {
- System.out.println("calculating FibonacciJava7(" n ")");
- result = fibonacciJava7(n - 2) fibonacciJava7(n - 1);
- cache.put(n, result);
- }
- }
- }
- return result;
- }
- }
三、程序运行结果
- calculating Fibonacci(7)
- calculating Fibonacci(5)
- calculating Fibonacci(3)
- calculating Fibonacci(2)
- calculating Fibonacci(4)
- calculating Fibonacci(2)
- calculating Fibonacci(3)
- calculating Fibonacci(2)
- calculating Fibonacci(6)
- calculating Fibonacci(4)
- calculating Fibonacci(2)
- calculating Fibonacci(3)
- calculating Fibonacci(2)
- calculating Fibonacci(5)
- calculating Fibonacci(3)
- calculating Fibonacci(2)
- calculating Fibonacci(4)
- calculating Fibonacci(2)
- calculating Fibonacci(3)
- calculating Fibonacci(2)
- Fibonacci(7) = 13
- calculating FibonacciJava8 7
- calculating FibonacciJava8 5
- calculating FibonacciJava8 3
- calculating FibonacciJava8 2
- calculating FibonacciJava8 4
- calculating FibonacciJava8 6
- FibonacciJava8(7) = 13
- FibonacciJava7(7) = 13
- {fruits=[orange, banana, apple, pear, water]}
- ===
- ===
- ===
- ===
- {name=name2, mobile=mobile2, addr=addr2, email=email2}
原文链接:http://my.oschina.net/cloudcoder/blog/217775
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /news/detail/tanhcceihf
系列文章
更多
同类精品
更多
-
2023 年度 A 类学科竞赛项目清单
那个人有梦想 09-16 -
从《银行业金融机构数据治理指引》监管要求看商业银行数据能力建设
51CTO 09-21 -
爱思唯尔的ESWA——模板、投稿、返修、接收的
老板来碗小面加蛋~ 09-16 -
国航天科技集团公司的各个研究院
知识在于积累 09-17 -
全球WIFI功率信号最强的国家清单,无线WIFI调优
Cisco_VIP 09-17 -
AI绘画Midjourney的咒语关键词汇
毕设小程序软件程序猿 09-17 -
ChatGPT注册流程攻略,含验证码接收
PHP中文网 05-29 -
创作者身份认证申请规则和审核标准
CSDN官方博客 09-16 -
的10 个顶尖的国内外设计网站
四喜圆子- 09-16 -
OBS做绿幕直播滤镜实现去掉绿色背景
视频砖家 09-16