Guava 是谷歌推荐使用的 java 开源库,是一个非常好用且丰富的工具类库,其中包含了集合、字符串、缓存、异常验证、io流操作等处理场景。把 Guava 用在项目中, 它会让你的编码变得十分的简洁、高效。
在项目中引入maven的包:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
接下来例举日常开发中几个常见的场景:
场景一:对数据进行分组
ArrayList<Product> productList = Lists.newArrayList(
new Product("小米", 1),
new Product("华为", 1),
new Product("宝马", 2),
new Product("三星", 1),
new Product("菠萝", 3),
new Product("奔驰", 2),
new Product("西瓜", 3)
);
有以上的产品列表数据,我们需要将它们以产品分类id(categoryId)进行分组。通常的做法基本就是将集合进行遍历,然后利用 Map 的键不可重复的特性,将列表按照键来分组
Map<Integer, List<Product>> productGroupMap = new HashMap<>();
for (Product product : productList) {
Integer categoryId = product.getCategoryId();
List<Product> groupList = productGroupMap.get(categoryId);
if (groupList == null) {
groupList = new ArrayList<>();
}
// 将产品添加进该组列表
groupList.add(product);
// 将该组列表归到该分类id
productGroupMap.put(categoryId, groupList);
}
这么做当然能完成功能,但是有没有更简洁高效的做法呢?接下来我们看看利用Guava中的 HashMultimap
如何来完成。
Multimap<Integer, Product> productMap = HashMultimap.create();
for (Product product : productList) {
productMap.put(product.getCategoryId(), product);
}
就是这么简单地搞定了。
首先创建了一个 HashMultimap
对象,它的Key对应的是 categoryId ,它的Value实际上对应的是一个类型为 Product 的 Collection
集合。当遇到相同的 categoryId 时,HashMultimap 会把一个键映射到多个值中,这多个值会存储在 Collection 中,这样就相当于一个 categoryId 对应一个集合,很方便就完成了对产品的分组。可以看出来, HashMultimap 就是天生用来处理 Map
这种数据结构的集合,分组好之后取出其中一个分类看看效果
Collection<Product> products = productMap.get(3);
System.out.println(products);
// 输出结果: [Product{name='菠萝', categoryId=3}, Product{name='西瓜', categoryId=3}]
这里顺便提一下,JDK版本到了1.8的时候,也有相应的流式处理方案,可以达到相同效果,代码如下
Map<Integer, List<Product>> productsMap2 = productList.stream()
.collect(Collectors.groupingBy(Product::getCategoryId));
场景二:字符串的拼接处理
比如说我想把前端传过来的三个参数用“ - ”连接在一起,然后存到数据库的某一字段中,处理过程中,我们要先进行参数判空,接着是处理最后一个参数不拼接“ - ”,最简单粗暴的就是以下做法
List<String> list = Lists.newArrayList("attr1", "attr2", null, "attr3");
StringBuilder joinStr = new StringBuilder();
for (int i = 0, length = list.size(); i < length; i++) {
if (StringUtils.isNotBlank(list.get(i))) {
if (i < length - 1) {
joinStr.append(list.get(i));
joinStr.append("-");
} else {
joinStr.append(list.get(i));
}
}
}
// joinStr:attr1-attr2-attr3
如果利用Guava的连接器 Joiner
进行处理,十分地简洁
String result = Joiner.on("-").skipNulls().join(list);
// result:attr1-attr2-attr3
1、Joiner.on("-")
表示用“-”符号进行拼接
2、skipNulls()
表示跳过为null的字符串对象
3、join()
表示要拼接的字符串列表
场景三:参数校验,优雅地处理异常
比如说你想判断对象是否为null,是null的时候抛出异常,你可以这么做
Preconditions.checkNotNull(param, "参数不能为空");
而不用这样
if (param == null) {
throw new IllegalArgumentException("参数不能为空");
}
还有等等以下诸多功能:
// 检查expression表达式是否为真
checkArgument(boolean expression);
// 检查index是否为在指定的长度范围之内,size可以是字符串、集合、数组的长度
checkElementIndex(int index, int size);
等等等...
场景四:文件的操作
比如我要复制一个文件到另一个文件,Guava中可以这么做
File file = new File("F:/file.txt");
File newFile = new File("F:/newFile.txt");
Files.copy(file, newFile);
比如我想读取txt文件的每一行到List集合中,直接这样
List<String> list = Files.readLines(file, Charsets.UTF_8);
总结:除了以上常遇到的场景之外,Guava中还有许多好用的工具和类库,敬请参考官方Github:https://github.com/google/guava/wiki