guava 模块
Basic utilities
更方便的使用java
避免使用空值
reason:
95%的集合不应该接受null值,快速失败优于接受null值
为何使用null?
null表达的意义不明确,e.g map.get(key) 返回null,可能代表map中包含了这个值为null,或者根本不包含这个key值.
option <T> :
创建一个option:
1. Optional.of(T) 返回一个非空的集合,如果是空会快速失败
2. Optional.absent() 直接返回一个空对象
3. Optional.fromNullable(T) 返回一个可空的集合.
查询方法:
1. boolean isPresent() 如果不为空返回true
2. T get() 返回包含的值,否则返回 IllegalStateException
3. T or(T) 返回包含的值,否则返回 default 值
4. T orNull() 返回包含的值,否则返回 null
考虑的关键点:
就算返回null, 在包装之后调用方液必须考虑返回值为空的情况.
方便的使用方法:
1. 方便的使用默认值代替null
Objects.firstNonNull(T, T) 返回第一个不为空的值,都为空,返回nullpointer.
2. 使用 option.or 可以代替上述方法.
Preconditions 先决条件
API 使用方式:
1. 直接抛出异常
checkArgument(i >= 0);
2. 抛出额外的Object的message ,调用 extra object.toString
checkArgument(i >= 0,"error Message");
3. 使用未知替换符 %s
checkArgument(i < j, "Expected i < j, but %s > %s", i, j);
方法 | 描述 | 异常 |
---|---|---|
checkArgument(boolean) | 检查参数是否是true | IllegalArgumentException |
checkNotNull(T) | 检查参数是否是null | NullPointerException |
checkState(boolean) | 检查当前对象的状态,与入参无关的状态 | IllegalStateException |
checkElementIndex(int index, int size) | 检查当前未知是否在元素中 | IndexOutOfBoundsException |
Cache
example :
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
使用范围:
cache 和 ConcurrentMap 很相似,但是也有区别.
ConcurrentMap 保存所有已插入的项目直到呗明确的移除.
cache 自动删除内存中过期的数据.
LoadingCache 可以在内存中没有时,自动加载数据
* 使用更多的内存,加快速递
* 需要查询多次相同的key值
* 不会使用过多的内存.
使用方式:
是否可以使用去计算一个key值.
Y : 使用CacheLoader
N : 传入Callable进入get方法
- 使用cacheLoader方式
这里内部加载缓存的方法会抛出检查性异常,会在get方法获取时抛出ExecutionException.
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.maximumSize(1000)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) throws AnyException {
return createExpensiveGraph(key);
}
});
...
try {
return graphs.get(key);
} catch (ExecutionException e) {
throw new OtherException(e.getCause());
}
非检查性异常方式:
LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build(
new CacheLoader<Key, Graph>() {
public Graph load(Key key) { // no checked exception
return createExpensiveGraph(key);
}
});
...
return graphs.getUnchecked(key);
-
使用Callable:
Cache<Key, Value> cache = CacheBuilder.newBuilder() .maximumSize(1000) .build(); // look Ma, no CacheLoader ... try { // If the key wasn't in the "easy to compute" group, we need to // do things the hard way. cache.get(key, new Callable<Value>() { @Override public Value call() throws AnyException { return doThingsTheHardWay(key); } }); } catch (ExecutionException e) { throw new OtherException(e.getCause()); }
过期策略:
- Size-based Eviction 基于大小的过期策略 :
CacheBuilder.maximumSize(long) 大小不超过参数值.
CacheBuilder.maximumWeight(long) 计算传入参数的大小(内存大小值等)LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder() .maximumWeight(100000) .weigher(new Weigher<Key, Graph>() { public int weigh(Key k, Graph g) { return g.vertices().size(); } }) .build( new CacheLoader<Key, Graph>() { public Graph load(Key key) { // no checked exception return createExpensiveGraph(key); } } );
- 基于时间的过期策略:
expireAfterAccess(long, TimeUnit) 基础时间内没有访问过
expireAfterWrite(long, TimeUnit) 基础时间内有过创建或有过更改