guava 模塊
Basic utilities
更方便的使用java
避免使用空值
reason:
95%的集合不應(yīng)該接受null值,快速失敗優(yōu)于接受null值
為何使用null?
null表達的意義不明確,e.g map.get(key) 返回null,可能代表map中包含了這個值為null,或者根本不包含這個key值.
option <T> :
創(chuàng)建一個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
考慮的關(guān)鍵點:
就算返回null, 在包裝之后調(diào)用方液必須考慮返回值為空的情況.
方便的使用方法:
1. 方便的使用默認值代替null
Objects.firstNonNull(T, T) 返回第一個不為空的值,都為空,返回nullpointer.
2. 使用 option.or 可以代替上述方法.
Preconditions 先決條件
API 使用方式:
1. 直接拋出異常
checkArgument(i >= 0);
2. 拋出額外的Object的message ,調(diào)用 extra object.toString
checkArgument(i >= 0,"error Message");
3. 使用未知替換符 %s
checkArgument(i < j, "Expected i < j, but %s > %s", i, j);
方法 | 描述 | 異常 |
---|---|---|
checkArgument(boolean) | 檢查參數(shù)是否是true | IllegalArgumentException |
checkNotNull(T) | 檢查參數(shù)是否是null | NullPointerException |
checkState(boolean) | 檢查當前對象的狀態(tài),與入?yún)o關(guān)的狀態(tài) | 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 很相似,但是也有區(qū)別.
ConcurrentMap 保存所有已插入的項目直到唄明確的移除.
cache 自動刪除內(nèi)存中過期的數(shù)據(jù).
LoadingCache 可以在內(nèi)存中沒有時,自動加載數(shù)據(jù)
* 使用更多的內(nèi)存,加快速遞
* 需要查詢多次相同的key值
* 不會使用過多的內(nèi)存.
使用方式:
是否可以使用去計算一個key值.
Y : 使用CacheLoader
N : 傳入Callable進入get方法
- 使用cacheLoader方式
這里內(nèi)部加載緩存的方法會拋出檢查性異常,會在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) 大小不超過參數(shù)值.
CacheBuilder.maximumWeight(long) 計算傳入?yún)?shù)的大小(內(nèi)存大小值等)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) 基礎(chǔ)時間內(nèi)沒有訪問過
expireAfterWrite(long, TimeUnit) 基礎(chǔ)時間內(nèi)有過創(chuàng)建或有過更改