Java8 构建本地缓存

Posted mitsuhide1992

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8 构建本地缓存相关的知识,希望对你有一定的参考价值。

偶然想到了,之前一直用redis做key-value的缓存,为什么不能用HashMap用作缓存呢?
理由应该是redis中有很多封装好的功能,比如缓存持久化这种。

缓存实现

使用的ConcurrentHashMap做缓存,避免了递归的重复计算:

package cn.mitsuhide.Java8New;

import java.util.concurrent.ConcurrentHashMap;

/**
 * Created by baidu on 16/10/10.
 */
public class CacheHelper 
    private ConcurrentHashMap<Integer, Integer> cache = new ConcurrentHashMap<>();

    public static void main (String [] args) 
        CacheHelper ch = new CacheHelper();
        System.out.println(ch.fibonaacci(12));
        System.out.println(ch.fibonaacci(11));
    

    public int fibonaacci (int i) 
        if (i == 0 || i == 1) 
            return i;
        
        // Java 8 Map接口中新增方法
        // 首先判断缓存MAP中是否存在指定key的值,如果不存在,会自动调用mappingFunction(key)
        // 计算key的value,然后将key = value
        // 放入到缓存Map,java8会使用thread-safe的方式从cache中存取记录。
        return cache.computeIfAbsent(i, (key) -> 
            // 函数式接口,key = i,就是传过来的key,函数中的第一个参数
            System.out.println("Compute fibonaacci " + key);
            return fibonaacci(key - 1) + fibonaacci(key - 2);
        );
    

    public ConcurrentHashMap<Integer, Integer> getCache() 
        return cache;
    

    public void setCache(ConcurrentHashMap<Integer, Integer> cache) 
        this.cache = cache;
    

Java 8中的新功能

Function接口

如果你正在浏览Java8的API,你会发现java.util.function中 Function, Supplier, Consumer, Predicate和其他函数式接口广泛用在支持lambda表达式的API中。这些接口有一个抽象方法,会被lambda表达式的定义所覆盖。在这篇文章中,我会简单描述Function接口,该接口目前已发布在java.util.function中。

Function接口的主要方法:

R apply(T t) – 将Function对象应用到输入的参数上,然后返回计算结果。

default ‹V› Function‹T,V› – 将两个Function整合,并返回一个能够执行两个Function对象功能的Function对象。

译者注:Function接口中除了apply()之外全部接口如下:

default <V> Function<T,V> andThen(Function<? super R,? extends V> after) 返回一个先执行当前函数对象apply方法再执行after函数对象apply方法的函数对象。

default <V> Function<T,V> compose(Function<? super V,? extends T> before)返回一个先执行before函数对象apply方法再执行当前函数对象apply方法的函数对象。

static <T> Function<T,T> identity() 返回一个执行了apply()方法之后只会返回输入参数的函数对象。

http://ifeve.com/jjava-util-function-java8/

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

以上是关于Java8 构建本地缓存的主要内容,如果未能解决你的问题,请参考以下文章

探讨下如何更好的使用缓存 —— Redis缓存的特殊用法以及与本地缓存一起构建多级缓存的实现

缓存

函数式编程在Java8中使用Lambda表达式进行开发

JAVA缓存规范 —— 虽迟但到的JCache API与天生不俗的Spring Cache

图文并茂,带你入坑本地缓存 Caffeine

本地缓存