Guava LoadingCache不能缓存null值
测试的时候发现项目中的LoadingCache没有刷新,但是明明调用了refresh方法了。后来发现LoadingCache是不支持缓存null值的,如果load回调方法返回null,则在get的时候会抛出异常。
通过几个例子开看这个问题:
public void test_loadNull() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
System.out.println("xx");
if (s.equals("hello"))
return "world";
else
return null;
}
});
try {
System.out.println(stringCache.get("hello"));
// get触发load,load返回null则抛出异常:
// com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key other_key.
System.out.println(stringCache.get("other_key"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void test_loadNullWhenRefresh() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
int i = 0;
@Override
public String load(String s) throws Exception {
if (i == 0) {
i++;
return "world";
}
return null;
}
});
try {
System.out.println(stringCache.get("hello"));
System.out.println(stringCache.get("hello"));
// refresh的时候,如果load函数返回null,则refresh抛出异常:
// Exception thrown during refresh
// com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key hello.
stringCache.refresh("hello");
System.out.println(stringCache.get("hello"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void test_loadNullAfterInvalidate() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
int i = 0;
@Override
public String load(String s) throws Exception {
if (i == 0) {
i++;
return "world";
}
return null;
}
});
try {
System.out.println(stringCache.get("hello"));
System.out.println(stringCache.get("hello"));
// invalidate不会触发load
stringCache.invalidate("hello");
// invalidate后,再次get,触发load,抛出异常:
// com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key hello.
System.out.println(stringCache.get("hello"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void test_loadThrowException() {
LoadingCache<String, String> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, String>() {
@Override
public String load(String s) throws Exception {
if (s.equals("hello"))
return "world";
else
throw new IllegalArgumentException("only_hello");
}
});
try {
System.out.println(stringCache.get("hello"));
// get触发load,load抛出异常,get也会抛出封装后的异常:
// com.google.common.util.concurrent.UncheckedExecutionException: java.lang.IllegalArgumentException: only_hello
System.out.println(stringCache.get("other_key"));
} catch (ExecutionException e) {
e.printStackTrace();
}
}
所以如果你需要缓存“空”值,推荐的做法是使用Optional对象来封装结果:
public void test_loadUseOptional() {
LoadingCache<String, Optional<String>> stringCache = CacheBuilder.newBuilder()
.maximumSize(10)
.build(new CacheLoader<String, Optional<String>>() {
@Override
public Optional<String> load(String s) throws Exception {
if (s.equals("hello"))
return Optional.of("world");
else
return Optional.absent();
}
});
try {
Optional<String> hello = stringCache.get("hello");
if(hello.isPresent()) {
System.out.println(hello.get());
}
Optional<String> otherKey = stringCache.get("other_key");
if(otherKey.isPresent()){
System.out.println(otherKey.get());
}
} catch (ExecutionException e) {
e.printStackTrace();
}
}
如果你的场景中认为null是不存在的,那么你可以在load函数中抛出异常,这个异常会通过get抛出。
另外还有一个问题,如果是key==null呢?答案是直接抛出java.lang.NullPointerException
。Guava对于null是很不待见的。
参考资料
- [Google Guava] 3-缓存 | 并发编程网 – ifeve.com
http://ifeve.com/google-guava-cachesexplained/ - Guava Cache使用笔记 - 代码说-Let code talk - ITeye博客
http://bylijinnan.iteye.com/blog/2225074 - guava - How to avoid caching when values are null? - Stack Overflow
https://stackoverflow.com/questions/13379071/how-to-avoid-caching-when-values-are-null
本文独立博客地址:Guava LoadingCache不能缓存null值 | 木杉的博客
Guava LoadingCache不能缓存null值的更多相关文章
- Spring Cacheable 注解不缓存null值
用Cacheable注解时,发现空值,也会被缓存下来.如果我们期望空值不被缓存,可以做如下设置: @Cacheable(key = "#id", unless="#res ...
- 使用google guava做内存缓存
google guava中有cache包,此包提供内存缓存功能.内存缓存需要考虑很多问题,包括并发问题,缓存失效机制,内存不够用时缓存释放,缓存的命中率,缓存的移除等等. 当然这些东西guava都考虑 ...
- 本地缓存google.guava及分布式缓存redis 随笔
近期项目用到了缓存,我选用的是主流的google.guava作本地缓存,redis作分布式 缓存,先说说我对本地缓存和分布式缓存的理解吧,可能不太成熟的地方,大家指出,一起 学习.本地缓存的特点是速度 ...
- 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结
为什么说JAVA中要慎重使用继承 这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...
- 【Java必修课】四类方法删除List里面的所有null值
1 简介 万恶的null已经折磨程序员许久了,也带来了许多难以发现却造成严重损失的NullPointerException.我们需要尽可能的避免它,有一种简单的办法就是在它进入下轮处理前,我们就把它扼 ...
- oracle 关于null值排序
在oracle中根据字段来desc排序的话null值可能会在数据的最前面.然而有时候我们查看数据的时候并不希望能够在前面看到这些null值的排序数据. 因此我查了一下: 1.排序的时候运用nvl(). ...
- SQL中NULL值
SQL的表达式,除了IS NULL和NOT NULL以外,只要出现NULL值结果都为FALSE 简单的例子: SELECT * FROM table WHERE name!='abc' 只要name值 ...
- 关于null值的排序
关于空值null的排序问题 Oracle排序中NULL值处理的五种常用方法: 1.缺省Oracle在Order by 时缺省认为null是最大值,所以如果是ASC升序则排在最后,DESC降序则排在 ...
- SQL Server表分区的NULL值问题
SQL Server表分区的NULL值问题 SQL Server表分区只支持range分区这一种类型,但是本人觉得已经够用了 虽然MySQL支持四种分区类型:RANGE分区.LIST分区.HASH分区 ...
随机推荐
- eclipse修改快捷键
eclipse修改快捷键 ctrl + shift + l查看快捷键 window -> preferences -> 搜索keys 鼠标点击以下五个表头,可以按照内容搜索 示例,选中Bi ...
- 台电X16pro刷机记录
Android: 如果要刷安卓,需要使用win7系统电脑,且需要安装java环境,同时按住 音量减+电源键进入刷机模式(DNX BOOT MODE..),这时在PhoneFlashTool_5.3.2 ...
- 吴裕雄 python 机器学习——模型选择回归问题性能度量
from sklearn.metrics import mean_absolute_error,mean_squared_error #模型选择回归问题性能度量mean_absolute_error模 ...
- 定义列表dl中标签 dt 与标签dd对齐方法,标签ul与标签li对齐
不定义css样式时(默认情况): 代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...
- Unix系统级I/O
在Unix系统中,一且皆为文件.一个Linux文件就是一个字符序列,并且所有的I/O设备都被模型化成了文件.而所有的输入输出都被当作对对应文件的读和写.Linux提供了一组简单.低级的接口,使得所有的 ...
- 前端 9.16腾讯-2019校园招聘(正式卷)编程题题解(js)
第一题 和谐的数字 牛牛很喜欢研究数字.一天,他发明了一种数字,叫做“和谐的数字”. 和谐的数字定义如下: 定义S(n)为数字n各位数字之和,如果S(n)能够整除n,那么就称n为一个“和谐的数字”. ...
- OpenCV介绍
OpenCV 是什么 OpenCV是计算机视觉开源库,主要算法涉及图像处理和机器学习相关方法. 是 Intel 公司贡献出来的,俄罗斯工程师贡献大部分 C/C++ 代码 在多数图像处理相关的应用程序中 ...
- vue 中 限制 input 输入数字、小数位数等
限制小数位数 <input type="number" @keydown="handleInput2" placeholder="请输入或查看& ...
- 进程的用户ID
进程创建时,系统会在进程上设置几个用户相关的ID 实际用户ID,实际用户组ID,系统根据当前会话登陆的用户信息设置 有效用户ID,有效用户组ID,系统根据所打开的执行文件的模式位,进行设置.set_u ...
- CentOS 7控制台屏幕分辨率问题
我们在服务器上,很少会安装图形化界面,一般都使用字符界面的控制台.CentOS 下,控制台分辨率缺省情况下,变得很高,导致在显示器上花屏或者只能显示局部. 这是由于使用了frame buffer,好处 ...