0%

Google Guava 工具类的介绍和使用

概述

工具类就是封装平时常用的方法,不需要重复造轮子,今天介绍下谷歌的 guava。

guava 的优点:

  • 高效设计良好的API,被 Google 的开发者设计,实现和使用
  • 遵循高效的Java的语法实践
  • 使代码更刻度,简洁,简单
  • 节约时间,资源,提高生产力

Guava 工具包包含若干个 Google Java项目:

  • 集合
  • 缓存
  • 原生类型支持
  • 并发库
  • 通用注解
  • 字符串处理
  • I/O 等

在使用时,只需要在项目依赖中加入 Google Guava:

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>

集合

Google Guava 工具包提供了大量创建和使用集合的方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
// 普通 Collection 创建
List<String> list = Lists.newArrayList();
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();
// BiMap: 双向Map(Bidirectional Map)键和值不能重复
BiMap<String, String> biMap = HashBiMap.create();

// 不可变 Collection创建
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("a", "b", "c");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");
}

集合和特定字符串转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void main(String[] args) {
// 普通 Collection 创建
List<String> list = Lists.newArrayList();
Set<String> set = Sets.newHashSet();
Map<String, String> map = Maps.newHashMap();

// 不可变 Collection创建
ImmutableList<String> iList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> iSet = ImmutableSet.of("a", "b", "c");
ImmutableMap<String, String> iMap = ImmutableMap.of("k1", "v1", "k2", "v2");

// BiMap: 双向Map(Bidirectional Map)键和值不能重复
BiMap<String, Integer> biMap = HashBiMap.create();
biMap.put("张三",54);
biMap.put("李四",23);
biMap.put("程思",33);
biMap.put("吴楠",16);

//key相同value不同,后面的会覆盖前面的
biMap.put("吴楠",46);
//启动程序会报错 java.lang.IllegalArgumentException: value already present: 23
//biMap.put("张刚",23);
//强行添加,会覆盖
//biMap.forcePut("张刚",23);
System.out.println(biMap);
//反转 key和value反转
BiMap<Object, Object> inverseMap = biMap.inverse();
System.out.println(inverseMap);
}

将集合转换成特定字符串,很多工具都支持这个功能。

集合切割(Lists.partitions)

1
2
3
4
5
6
7
8
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
int num = 20;
for (int i = 0; i < num; i++) {
list.add(i);
}
System.out.println(Lists.partition(list, 5));
}

输出:

1
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12, 13, 14], [15, 16, 17, 18, 19]]

其他功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public static void main(String[] args) {
//反转list
List<String> reverseList1 = Lists.reverse(list);
System.out.println("反转:" + reverseList1);

// 集合过滤 [guava, Java]
ImmutableList<String> names = ImmutableList.of("code", "guava", "google", "alibaba", "Java", "Go");
Iterable<String> filterList = Iterables.filter(names, Predicates.or(
Predicates.equalTo("guava"), Predicates.equalTo("Java")));
System.out.println(filterList);

// 自定义过滤条件: {a=12, b=15}
ImmutableMap<String, Integer> m = ImmutableMap.of("a", 12, "b", 15);
// Function<F, T> 中 F表示apply()方法input的类型,T表示apply()返回的类型
Map<String, Integer> m2 = Maps.transformValues(m, new Function<Integer, Integer>() {
@Override
public @Nullable Integer apply(@Nullable Integer input) {
if (input > 12) {
return input;
} else {
return input++;
}
}
});
System.out.println(m);

// 交集、并集、差集
Set<String> set1 = Sets.newHashSet("a", "b", "c");
Set<String> set2 = Sets.newHashSet("a", "c", "d");
// 并集
Sets.SetView<String> union = Sets.union(set1, set2);
System.out.println("并集:" + union);
// 差集
Sets.SetView<String> difference = Sets.difference(set1, set2);
System.out.println("差集" + difference);
// 交集
Sets.SetView<String> intersection = Sets.intersection(set1, set2);
System.out.println("交集:" + intersection);
}

也支持很多Map的操作,现在列举一些基础使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
/**Map的常见用法*/
Map<String, Object> leftMap = ImmutableMap.of("name", "汪", "age", 18, "address", "陕西", "city", "西安", "love", "张");
Map<String, Object> rightMap = ImmutableMap.of("name", "张", "age", 16, "address", "陕西", "city", "西安", "home", "美国");
MapDifference<String, Object> deffMap = Maps.difference(leftMap, rightMap);
//相同的
Map<String, Object> map = deffMap.entriesInCommon();
System.out.println("相同的:" + map);
//同key不同value
Map<String, MapDifference.ValueDifference<Object>> stringValueDifferenceMap = deffMap.entriesDiffering();
System.out.println("同key不同value:" + stringValueDifferenceMap);
//仅仅左边有的
Map<String, Object> onlyLeft = deffMap.entriesOnlyOnLeft();
System.out.println("仅仅左边有的:" + onlyLeft);
//仅仅右边有的
Map<String, Object> onlyRight = deffMap.entriesOnlyOnRight();
System.out.println("仅仅右边有的:" + onlyRight);
}

字符串处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public static void main(String[] args) {
// 去除空格: [1, 2, 3, 4, 5, 6]
String str = "1-2-3-4- 5- 6 ";
List<String> trimList = Splitter.on("-")
.omitEmptyStrings()
// 可指定字符
.trimResults()
.splitToList(str);
System.out.println(trimList);

// String -> Map
String mapStr = "zhangsan=25,lisi=90";
Map<String, String> splitMap = Splitter.on(",")
.withKeyValueSeparator("=")
.split(mapStr);
System.out.println(splitMap);

// guava 支持多字符或者正则切分:[aa, dd, ff]
String input = "aa.dd,,ff,,.";
List<String> result = Splitter.onPattern("[.|,]")
.omitEmptyStrings()
.splitToList(input);
System.out.println(result);

System.out.println("==========CharMatcher===============");
// 匹配所有的
CharMatcher charMatcher1 = CharMatcher.any();
CharMatcher charMatcher2 = CharMatcher.anyOf("aef");
// 什么也不匹配的
CharMatcher charMatcher3 = CharMatcher.none();
// 匹配空白字符的
CharMatcher charMatcher4 = CharMatcher.whitespace();
CharMatcher charMatcher4_1 = CharMatcher.breakingWhitespace();
// 匹配单个字符
CharMatcher charMatcher5 = CharMatcher.is('a');
CharMatcher charMatcher6 = CharMatcher.isNot('a');
// 匹配范围
CharMatcher charMatcher7 = CharMatcher.inRange('0', '9');
CharMatcher charMatcher8 = CharMatcher.inRange('a', 'z');
CharMatcher charMatcher9 = CharMatcher.inRange('A', 'Z');

System.out.println("==========CaseFormat===============");
// 转驼峰:constantName
String lowerCamel = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, "CONSTANT_NAME");
System.out.println(lowerCamel);
// 转驼峰:ConstantName
String upperCamel = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, "CONSTANT_NAME");
System.out.println(upperCamel);
// 转小写:constant-name
String lowerHyphen = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, "CONSTANT_NAME");
System.out.println(lowerHyphen);
// 转小写:constant_name
String lowerUnderscore = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_UNDERSCORE, "CONSTANT_NAME");
System.out.println(lowerUnderscore);
// CONSTANT_NAME
String upperUnderscore = CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, "CONSTANT_NAME");
System.out.println(upperUnderscore);
}

并发库

ThreadFactoryBuilder

SettableFuture

ListenableFuture

Guava 定义了 ListenableFuture 接口并继承了JDK concurrent包下的Future 接口,扩展了一个addListener 监听方法,当任务执行完成,会主动回调该方法。主要也是弥补了JDK自带Future的不足,像Netty 也优雅的实现了异步回调机制,不需要手动通过 Future.get() 来获取结果。

Futures.addCallback

AsyncFunction

缓存

Guava Cache 可以作为本地缓存,支持很多方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public static void main(String[] args) throws ExecutionException, InterruptedException {
//google guava cache CacheBuilder的构造函数是私有的,在智能通过静态方法 newBuilder 来获取 CacheBuilder 实例
LoadingCache<Integer, String> cache = CacheBuilder.newBuilder()
//设置并发级别为8,并发级别是指可以同时写缓存的线程数
.concurrencyLevel(8)
//设置写缓存后8秒过期
.expireAfterWrite(8, TimeUnit.SECONDS)
//设置初始容量 10
.initialCapacity(10)
//设置缓存最大容量为100,超过100之后就会按照 LRU 最近最少使用算法来移除缓存
.maximumSize(100)
//定时刷新数据
.refreshAfterWrite(1, TimeUnit.SECONDS)
//设置要统计缓存的命中率
.recordStats()
//设置缓存移除通知
.removalListener(new RemovalListener<Object, Object>() {
@Override
public void onRemoval(RemovalNotification<Object, Object> notification) {
System.out.println(notification.getKey() + " was removed, cause is" + notification.getCause());
}
})
.build(
//build 方法可以指定CacheLoader,在缓存不存在是通过CacheLoader的实现自动加载缓存
new CacheLoader<Integer, String>() {
@Override
public String load(Integer key) throws Exception {
System.out.println("load data: " + key);
String str = key + ":cache-value";
return str;
}
}
);
for (int i = 0; i < 20; i++) {
String str = cache.get(1);
System.out.println(str);
//休眠一秒
TimeUnit.SECONDS.sleep(1);
}

System.out.println("cache status:");

System.out.println(cache.stats().toString());
}

文件I/O

1
2
3
4
5
6
7
8
9
10
11
public static void main(String[] args) {
File file = new File("D:\\Document\\temp\\test.txt");
List<String> list = null;
try {
list = Files.readLines(file, Charsets.UTF_8);
}catch (Exception e){
}
// 文件拷贝
Files.copy(form, to);
Files.move(File from, File to);
}
客官,赏一杯coffee嘛~~~~