Guava 常用功能
guava 是 google 项目团队多年沉淀下来的工具包,在现代的分布式系统中得到广泛的应用。
基于最新版本 Guava:
<!-- https://mvnrepository.com/artifact/com.google.guava/guava --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>31.1-jre</version> </dependency>
文章目录
guava.common
Precondition
异常判断
public static void main(String[] args) {
TestPrecondition condition = new TestPrecondition();
// 静态引入,
condition = checkNotNull(condition);
// 建议静态引入,提升效率import static com.google.common.base.Preconditions.checkArgument
checkArgument(args.length == 0, "args %s missing. ", args.length);
checkState(args.length == 0, "args not running");
System.out.println(condition.toString());
}
@Override
public String toString() {
// 输出 TestPrecondition{name='zs', id=1}
return MoreObjects.toStringHelper(this)
.add("name", name)
.add("id", id)
.add("petName", petName)
// 剔除为空的属性
.omitNullValues()
.toString();
}
CharMatcher
public static void main(String[] args) {
// CharMatcher 字符比较器,封装了常用字符比较算法
String charMatcherResult = CharMatcher
// 匹配字符 '0' ~ '9'
.inRange('0', '9')
// 或者:匹配任意字符 'a','b','c'
.or(CharMatcher.anyOf("abc"))
// 或者:不属于以下字符 'z' 'd' 'a' 'd' 'f'
.or(CharMatcher.noneOf("zdadf"))
// 或者:等于 '-'
.or(CharMatcher.is('-'))
// 原始字符
.retainFrom("zdasd0dfdf-");
// 结果 as0-
System.out.println(charMatcherResult);
}
Comparators
public static void main(String[] args) {
// JDK 原有比较器,tzId1,tzId2 是正序还是逆序?比较难于阅读
Comparator<String> byReverserOffsetThenName = new Comparator<String>() {
@Override
public int compare(String tzId1, String tzId2) {
int offset1 = tzId1 == null ? -1 : tzId1.indexOf("id");
int offset2 = tzId2 == null ? -1 : tzId2.indexOf("id");
int result = offset2 - offset1;
return result == 0 ? tzId1.compareTo(tzId2) : result;
}
};
Lists.newArrayList("aid", "ida", "idb", "bid").sort(byReverserOffsetThenName);
// guava 提供 ComparisonChain 机制,代码更清晰易懂
Ordering<String> byReverserOffsetThenName2 = new Ordering<String>() {
@Override
public int compare(String tzId1, String tzId2) {
return ComparisonChain.start()
.compare(tzId1 == null ? -1 : tzId1.indexOf("id"), tzId2 == null ? -1 : tzId2.indexOf("id"))
.compare(tzId1, tzId2)
.result();
}
};
// Ordering 函数
Ordering<String> cityOrdering = Ordering.from(byReverserOffsetThenName);
ArrayList<String> list = Lists.newArrayList("aid", "ida", "idb", "bid");
Lists.newArrayList("aid", "ida", "idb", "bid").sort(cityOrdering);
list.sort(byReverserOffsetThenName2);
list.forEach(System.out::println);
Ordering.natural().reverse().thenComparing((a, b) -> a.toString().compareTo(b.toString()));
}
Optional
public static void main(String[] args) {
final TestOptional obj = new TestOptional();
// Optional
Optional<TestOptional> optional = Optional.of(obj);
// 使用 or 提供为空默认值
System.out.println(optional.or(new TestOptional()));
// 使用 Optional 做数据转换
optional.transform(c -> c.equals(obj)).get();
}
Splitter
public static void main(String[] args) {
// Splitter
String str = " foo, ,bar, quux,";
// 字符串 Splitter
Iterable<String> result = Splitter.on(',')
// 移除字符串前后空格
.trimResults()
// 移除为空或者为 null
.omitEmptyStrings()
.split(str);
result.forEach(System.out::println);
// 字符串 Joiner
System.out.println(Joiner.on(", ")
// 跳过为 null 的元素
.skipNulls()
.join(result));
}
Stopwatch
public static void main(String[] args) {
// stopWatch 相对时间, System.nanoTime() 的替代
Stopwatch stopWatch = Stopwatch.createStarted();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获得 stopWatch start() 以来经过的时间
Duration time1 = stopWatch.elapsed();
System.out.println(time1.toMillis());
// 停止 stopWatch
stopWatch.stop();
}
guava.collection
Hash
public static void main(String[] args) {
TestHash obj = new TestHash();
obj.setAge(18);
obj.setId(100000000l);
// 指定对象分解为原生字段值
Funnel<Pet> petFunnel = new Funnel<Pet>() {
private static final long serialVersionUID = -5516438913441382127L;
@Override
public void funnel(Pet from, PrimitiveSink into) {
into.putString(from.getName(), Charset.defaultCharset());
}
};
// 为了减少 hash 冲突,解决 JDK 自带 hashCode() 长度限制为 32 位,无插件机制等问题
HashCode hash =
// 支持算法切换 md5,sha1, sha256, sha512
// Hashing.goodFastHash(32) 让 guava 帮你选择 hash 算法
Hashing.murmur3_128().newHasher()
// 加入顺序不同,得到的 hash 值不同
.putInt(obj.getAge())
.putLong(obj.getId())
.putObject(obj.getPet(), petFunnel)
.hash();
System.out.println(hash);
System.out.println(hash.asInt());
System.out.println(hash.asLong());
}
BloomFilter
public static void main(String[] args) {
// 布隆过滤器
//
// 牺牲了正确率和时间以节省空间
// public boolean mightContain(T);
// true: 该元素不一定在集合中
// false: 该元素一定不在集合中
//
// 预计大小 = 500,预计 99.99 使用率
BloomFilter<Integer> filter = BloomFilter.create(
Funnels.integerFunnel(),
500,
0.01);
System.out.println(filter.put(50));
System.out.println(filter.put(150));
System.out.println(filter.put(250));
System.out.println(filter.put(350));
System.out.println(filter.put(450));
System.out.println(filter.put(550));
System.out.println(filter.put(650));
System.out.println(filter.put(750));
System.out.println(filter.put(850));
System.out.println(filter.put(950));
System.out.println(filter.mightContain(150));
System.out.println(filter.mightContain(250));
System.out.println(filter.mightContain(25));
}
ImmutableCollections
public static void main(String[] args) {
// ImmutableCollection 类似 JDK 的线程安全的不可变集合
ImmutableList<String> list = ImmutableList.of("a", "b", "c", "d");
ImmutableList<String> list2 = ImmutableList.of("a", "b", "c", "d", "e");
// 使用 copyOf 修改 ImmutableList
list = ImmutableList.copyOf(list2);
list.forEach(System.out::println);
// 初始化示栗
ImmutableSet<String> set = ImmutableSet.<String>builder()
.addAll(list2)
.add("f")
.build();
set.forEach(System.out::println);
}
Multimap
public static void main(String[] args) {
// Multimap 的使用 Multimap 类似于 Java 的 Map<String, Collection<String>>
Multimap<String, String> map = HashMultimap.create();
map.put("a", "1");
map.put("a", "1");
map.put("a", "2");
map.put("b", "2");
Collection<String> c = map.get("c");
// 输出为 0
System.out.println(c.size());
// 输出为 true
System.out.println(map.containsKey("a"));
// size = 3
System.out.println("size=" + map.size());
// ListMultimap 类似于 Java 的 Map<String, List<String>>
ListMultimap<String, String> listMultimap = ArrayListMultimap.create();
listMultimap.put("a", "1");
listMultimap.put("a", "1");
listMultimap.put("b", "1");
listMultimap.put("b", "2");
// 输出 [1, 2]
System.out.println(listMultimap.get("b"));
// 输出 {a=[1, 1], b=[1, 2]}
System.out.println(listMultimap);
// k,v 都不能重复,否则会报错
BiMap<String, String> biMap = HashBiMap.create();
biMap.put("a", "1");
biMap.put("b", "2");
BiMap<String,String> biMap2 = biMap.inverse();
// 输出 1:a \n 2:b
biMap2.forEach((k, v) -> System.out.println(k + ":" + v));
}
Multiset
public static void main(String[] args) {
// 类似于 HashMap<String, Integer>()
Multiset<String> multiset = HashMultiset.create();
multiset.add("aa");
multiset.add("aa");
multiset.add("bb");
// 输出 2
System.out.println(multiset.count("aa"));
// 输出 3
System.out.println(multiset.size());
// 输出 aa \n bb \n cc \n
Iterator<String> iter = multiset.iterator();
while (iter.hasNext()) {
String str = iter.next();
System.out.println(str);
}
System.out.println("-------------------");
// 输出 aa \n bb \n
for (String str : multiset.elementSet()) {
System.out.println(str);
}
}
Table
public static void main(String[] args) {
// table 类似于数据库的 table 结果结构 R = 主键 ,C = 列名,V = 值
Table<Integer, Character, String> table = ArrayTable.create(
// 主键序列 1, 2, 3
ImmutableList.of(1, 2, 3),
// 列定义序列:'A', 'B', 'C'
ImmutableList.of('A', 'B', 'C'));
// 相当于 Map<R, Map<C, V>>
table.put(1, 'A', "1A");
table.put(1, 'B', "1B");
table.put(2, 'A', "2A");
// 输出为 2A
System.out.println(table.get(2, 'A'));
// 输出为 1 \n 2 \n 3 \n
table.rowKeySet().forEach(System.out::println);
/*
* 1:A:1A
* 1:B:1B
* 1:C:null
* 2:A:2A
* 2:B:null
* 2:C:null
* 3:A:null
* 3:B:null
* 3:C:null
*/
table.cellSet().forEach(cell -> System.out.println(cell.getRowKey() + ":" + cell.getColumnKey() + ":" + cell.getValue()));
HashBasedTable<Integer, Character, String> hashTable = HashBasedTable.create();
// 输出为 {}
System.out.println(hashTable);
}
guava.func 函数式编程
Predicate
public static void main(String[] args) {
// guava 函数式编程,谓词函数,返回值为 布尔 类型
Predicate<TestFPredicate> fp = new Predicate<TestFPredicate>() {
@Override
public boolean apply(TestFPredicate input) {
return true;
}
};
// Predicate 谓词函数使用示栗
List<TestFPredicate> list = Lists.newArrayList(new TestFPredicate(), new TestFPredicate());
// FluentIterable 类似于 stream
ImmutableList<String> resultList = FluentIterable
.from(list)
.filter(fp)
.transform(Functions.toStringFunction())
.limit(10)
.toList();
resultList.forEach(System.out::println);
// FluentIterable 可以是哦那个 cycle 循环
boolean allMatch = FluentIterable.from(list)
.skip(0)
.cycle()
.limit(10)
.allMatch(a -> !a.equals(new TestFPredicate()));
System.out.println(allMatch);
}
Functional
public static void main(String[] args) {
List<String> strings = Lists.newArrayList("aa", "AA", "cc", "BB");
// 函数式编程,获得字符串的长度
Function<String, Integer> lengthFunction = new Function<String, Integer>() {
@Override
public Integer apply(String input) {
return input.length();
}
};
// 函数式编程,谓词函数,判断一个字符串是否只包含大写
Predicate<String> allCaps = new Predicate<String>() {
@SuppressWarnings("deprecation")
@Override
public boolean apply(String input) {
return CharMatcher.javaUpperCase().matchesAllOf(input);
}
};
// lengthFunction 和 allCaps 使用示栗 Iterables.transform
Multiset<Integer> lengths = HashMultiset.create(
Iterables.transform(Iterables.filter(strings, allCaps), lengthFunction)
);
lengths.forEach(System.out::println);
}
guava.cache
Cache
public static void main(String[] args) {
//
CacheLoader<String, String> loader = new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
if ("a".equals(key)) {
return "1";
}
if ("b".equals(key)) {
return "2";
}
return "3";
}
};
// 初始化缓存
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(2000)
.expireAfterAccess(10, TimeUnit.SECONDS)
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
System.out.println("removing..." + notification.getKey());
}
})
.build(loader);
try {
String value = cache.get("a");
System.out.println(value);
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// Guava 建议使用 LoadingCache 而不是 Cache
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(loader);
cache.put("a", "b");
System.out.println("size = " + cache.size());
System.out.println("a = " + cache.getUnchecked("a"));
System.out.println("b = " + cache.getUnchecked("b"));
}
public static void main(String[] args) {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
// 允许垃圾收集器回收
.softValues()
.build(loader);
String spec = "maximumSize=2000,expireAfterWrite=2m";
LoadingCache<String, String> cache2 = CacheBuilder.from(spec)
.build(loader);
cache.put("a", "b");
cache2.put("a", "b");
System.out.println("size = " + cache.size());
System.out.println("a = " + cache.getUnchecked("a"));
System.out.println("b = " + cache.getUnchecked("b"));
}
public static void main(String[] args) {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
// 当key 被 JVM GC 回收时,自动移除该 key
.weakKeys()
.build(loader);
cache.put("a", "b");
System.out.println("size = " + cache.size());
System.out.println("a = " + cache.getUnchecked("a"));
System.out.println("new String(a) = " + cache.getUnchecked(new String("a")));
System.out.println("b = " + cache.getUnchecked("b"));
}
public static void main(String[] args) {
// CacheLoader,相当于缓存的 init 方法,用于从持久化存储中读取缓存内容
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
// 读取单个 key
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}
// 与 cache.getAll 相对应的,loadAll,批量读取,提升效率
@Override
public Map<String, String> loadAll(Iterable<? extends String> keys) throws Exception {
Map<String, String> result = Maps.newHashMap();
System.out.println("------------------------getAll 会批量读取------------------------");
for (String key : keys) {
result.put(key, key.toUpperCase());
}
return result;
}
};
LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(loader);
cache.put("a", "b");
// 输出 a=b
cache.getAllPresent(Iterables.concat(Lists.newArrayList("a", "b", "c"))).forEach((k, v) -> System.out.println(k + "=" + v));
System.out.println("=========================================================");
try {
/**
* 输出
* ------------------------getAll 会批量读取------------------------
* a=b
* b=B
* c=C
*/
cache.getAll(Iterables.concat(Lists.newArrayList("a", "b", "c"))).forEach((k, v) -> System.out.println(k + "=" + v));
} catch (ExecutionException e) {
e.printStackTrace();
};
// 输出 size = 3
System.out.println("size = " + cache.size());
// 输出 a = b
System.out.println("a = " + cache.getUnchecked("a"));
// 输出 b = B
System.out.println("b = " + cache.getUnchecked("b"));
}
public static void main(String[] args) {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return loadFromeDisk(key);
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(loader);
cache.put("a", "b");
System.out.println("size = " + cache.size());
// CheckedException
System.out.println("a = " + cache.getUnchecked("a"));
System.out.println("b = " + cache.getUnchecked("b"));
}
protected static String loadFromeDisk(String key) throws ExecutionException {
throw new ExecutionException("not exists", new Throwable("not exists2"));
}
public static void main(String[] args) {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
System.out.println(notification.getKey() + ":" + notification.getValue());
}
})
.build(loader);
cache.put("a", "1");
cache.put("b", "2");
cache.put("c", "3");
cache.put("d", "4");
/*
* d:4
* b:2
* c:3
* a:1
*/
cache.invalidateAll();
// 设置 maximumSize=0,标识禁用该缓存
cache = CacheBuilder.from("maximumSize=0").build(loader);
cache.put("a", "1");
cache.put("b", "2");
cache.put("c", "3");
// 输出为 A
System.out.println(cache.getUnchecked("a"));
}
public static void main(String[] args) {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
// 最大缓存数
.maximumSize(2000)
.build(loader);
LoadingCache<String, String> cache2 = CacheBuilder.newBuilder()
// 使用 weight 替代 最大缓存数
.weigher((s1, s2) -> s2.toString().length())
.maximumWeight(20000)
.build(loader);
LoadingCache<String, String> cache3 = CacheBuilder.newBuilder()
// 记录缓存命中率等统计信息
.recordStats()
.build(loader);
LoadingCache<String, String> cache4 = CacheBuilder.newBuilder()
// 2 秒不使用
.expireAfterAccess(2, TimeUnit.SECONDS)
.build(loader);
LoadingCache<String, String> cache5 = CacheBuilder.newBuilder()
// 写入 2 秒后
.expireAfterWrite(2, TimeUnit.SECONDS)
.build(loader);
LoadingCache<String, String> cache6 = CacheBuilder.newBuilder()
// 写入 2 秒后,自动获得新数据
.refreshAfterWrite(2, TimeUnit.SECONDS)
.build(loader);
CacheStats stats = cache3.stats();
// 命中率,输出 1.0
System.out.println(stats.hitRate());
cache.put("a", "b");
cache2.put("a", "b");
cache4.put("a", "b");
cache5.put("a", "b");
cache6.put("a", "b");
// 输出 size = 1
System.out.println("size = " + cache.size());
// 输出 a = b
System.out.println("a = " + cache.getUnchecked("a"));
// 输出 b = B
System.out.println("b = " + cache.getUnchecked("b"));
}
public static void main(String[] args) throws ExecutionException {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder().build(loader);
System.out.println("size = " + cache.size());
String key = "1";
// 使用 Callable 指定获得值的方法
String v = cache.get(key, new Callable<String>() {
@Override
public String call() throws Exception {
return key.toLowerCase();
}
});
System.out.println("v=" + v);
}
public static void main(String[] args) {
CacheLoader<String, String> loader = new CacheLoader<String, String>(){
@Override
public String load(String key) throws Exception {
return key.toUpperCase();
}};
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(2000)
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
// 当数量达到 2000 时,可以通过 RemovalListener 收到通知
if (notification.wasEvicted()) {
}
}
})
.build(loader);
LoadingCache<String, String> cache2 = CacheBuilder.newBuilder()
.maximumSize(2000)
// 异步的移除监听
.removalListener(RemovalListeners.asynchronous(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
// 当数量达到 2000 时,可以通过 RemovalListener 收到通知
if (notification.wasEvicted()) {
}
}
}, new ScheduledThreadPoolExecutor(2)))
.build(loader);
cache.put("a", "b");
cache2.put("a", "b");
System.out.println("size = " + cache.size());
System.out.println("a = " + cache.getUnchecked("a"));
System.out.println("b = " + cache.getUnchecked("b"));
}