简介

Guava 是 Google 开源的 Java 核心库,提供了丰富的工具类和集合框架,能够极大提升开发效率。本文将介绍 Guava 中最常用的工具包及其实际应用。
1. 集合工具 (Collections)
1.1 不可变集合
不可变集合线程安全且不可修改,适合作为常量使用。
java
// 创建不可变 List
ImmutableList<String> list = ImmutableList.of("A", "B", "C");
// 创建不可变 Set
ImmutableSet<Integer> set = ImmutableSet.of(1, 2, 3, 4, 5);
// 创建不可变 Map
ImmutableMap<String, Integer> map = ImmutableMap.of(
"Java", 1,
"Python", 2,
"Go", 3
);
// 使用 Builder 构建复杂集合
ImmutableList<String> complexList = ImmutableList.<String>builder()
.add("A")
.add("B", "C")
.addAll(Arrays.asList("D", "E"))
.build();
1.2 Multiset - 计数集合
Multiset 允许元素重复,并可以统计元素出现次数。
java
Multiset<String> multiset = HashMultiset.create();
multiset.add("apple");
multiset.add("apple");
multiset.add("banana");
multiset.add("apple");
System.out.println(multiset.count("apple")); // 输出: 3
System.out.println(multiset.size()); // 输出: 4
// 遍历不重复元素
for (String element : multiset.elementSet()) {
System.out.println(element + ": " + multiset.count(element));
}
1.3 Multimap - 一键多值映射
Multimap 允许一个键对应多个值。
java
Multimap<String, String> multimap = ArrayListMultimap.create();
multimap.put("Fruit", "Apple");
multimap.put("Fruit", "Banana");
multimap.put("Vegetable", "Carrot");
System.out.println(multimap.get("Fruit")); // 输出: [Apple, Banana]
// 转换为普通 Map
Map<String, Collection<String>> map = multimap.asMap();
1.4 BiMap - 双向映射
BiMap 提供键值互查的双向映射。
java
BiMap<String, Integer> biMap = HashBiMap.create();
biMap.put("Alice", 1);
biMap.put("Bob", 2);
// 正向查询
System.out.println(biMap.get("Alice")); // 输出: 1
// 反向查询
System.out.println(biMap.inverse().get(1)); // 输出: Alice
1.5 Table - 双键映射
Table 提供行列式的双键映射结构。
java
Table<String, String, Integer> table = HashBasedTable.create();
table.put("2023", "Q1", 100);
table.put("2023", "Q2", 150);
table.put("2024", "Q1", 120);
// 获取值
Integer value = table.get("2023", "Q1"); // 100
// 获取某一行的所有数据
Map<String, Integer> row = table.row("2023"); // {Q1=100, Q2=150}
// 获取某一列的所有数据
Map<String, Integer> column = table.column("Q1"); // {2023=100, 2024=120}
2. 字符串工具 (Strings)
2.1 Joiner - 连接器
java
// 基本连接
String result = Joiner.on(", ").join(Arrays.asList("A", "B", "C"));
// 输出: A, B, C
// 跳过 null 值
String withoutNull = Joiner.on(", ")
.skipNulls()
.join("A", null, "B", "C");
// 输出: A, B, C
// 替换 null 值
String replaceNull = Joiner.on(", ")
.useForNull("N/A")
.join("A", null, "B");
// 输出: A, N/A, B
// Map 连接
Map<String, String> map = ImmutableMap.of("name", "John", "age", "30");
String mapStr = Joiner.on("&").withKeyValueSeparator("=").join(map);
// 输出: name=John&age=30
2.2 Splitter - 分割器
java
// 基本分割
Iterable<String> parts = Splitter.on(',').split("A,B,C");
// 去除空白字符
Iterable<String> trimmed = Splitter.on(',')
.trimResults()
.split(" A , B , C ");
// 忽略空字符串
Iterable<String> noEmpty = Splitter.on(',')
.omitEmptyStrings()
.split("A,,B,C");
// 限制分割数量
Iterable<String> limited = Splitter.on(',')
.limit(2)
.split("A,B,C,D");
// 结果: [A, B,C,D]
// 分割 Map
Map<String, String> kvMap = Splitter.on('&')
.withKeyValueSeparator('=')
.split("name=John&age=30");
2.3 Strings 工具类
java
// null 转空字符串
String str = Strings.nullToEmpty(null); // ""
// 空字符串转 null
String nullStr = Strings.emptyToNull(""); // null
// 字符串填充
String padded = Strings.padStart("7", 3, '0'); // "007"
String paddedEnd = Strings.padEnd("7", 3, '0'); // "700"
// 重复字符串
String repeated = Strings.repeat("ab", 3); // "ababab"
// 公共前缀
String prefix = Strings.commonPrefix("testing", "test"); // "test"
// 公共后缀
String suffix = Strings.commonSuffix("testing", "interesting"); // "ting"
3. 缓存工具 (Cache)
Guava Cache 提供本地缓存功能,支持多种过期策略。
java
LoadingCache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000) // 最大容量
.expireAfterWrite(10, TimeUnit.MINUTES) // 写入后过期
.expireAfterAccess(5, TimeUnit.MINUTES) // 访问后过期
.recordStats() // 启用统计
.build(new CacheLoader<String, String>() {
@Override
public String load(String key) throws Exception {
return loadFromDatabase(key); // 缓存加载逻辑
}
});
// 使用缓存
try {
String value = cache.get("key");
} catch (ExecutionException e) {
e.printStackTrace();
}
// 手动放入
cache.put("key", "value");
// 失效缓存
cache.invalidate("key");
// 查看统计
CacheStats stats = cache.stats();
System.out.println("命中率: " + stats.hitRate());
4. 集合工具类 (Lists, Sets, Maps)
4.1 Lists 工具
java
// 创建 ArrayList
List<String> list = Lists.newArrayList("A", "B", "C");
// 指定容量
List<String> capacityList = Lists.newArrayListWithCapacity(100);
// 反转列表
List<String> reversed = Lists.reverse(list);
// 分区
List<List<String>> partitions = Lists.partition(list, 2);
// 结果: [[A, B], [C]]
// 笛卡尔积
List<List<String>> cartesian = Lists.cartesianProduct(
Lists.newArrayList("A", "B"),
Lists.newArrayList("1", "2")
);
// 结果: [[A, 1], [A, 2], [B, 1], [B, 2]]
4.2 Sets 工具
java
// 创建 HashSet
Set<String> set1 = Sets.newHashSet("A", "B", "C");
Set<String> set2 = Sets.newHashSet("B", "C", "D");
// 并集
Set<String> union = Sets.union(set1, set2); // [A, B, C, D]
// 交集
Set<String> intersection = Sets.intersection(set1, set2); // [B, C]
// 差集
Set<String> difference = Sets.difference(set1, set2); // [A]
// 对称差集
Set<String> symmetricDifference = Sets.symmetricDifference(set1, set2); // [A, D]
// 幂集
Set<Set<String>> powerSet = Sets.powerSet(Sets.newHashSet("A", "B"));
// 结果: [[], [A], [B], [A, B]]
4.3 Maps 工具
java
// 创建 HashMap
Map<String, Integer> map = Maps.newHashMap();
// 从 Set 创建 Map
Set<String> keys = Sets.newHashSet("A", "B", "C");
Map<String, String> mapFromKeys = Maps.asMap(keys, key -> key.toLowerCase());
// 过滤 Map
Map<String, Integer> filtered = Maps.filterKeys(map, key -> key.startsWith("A"));
// 转换 Map 值
Map<String, String> transformed = Maps.transformValues(map, value -> "Value: " + value);
// 差异比较
MapDifference<String, Integer> diff = Maps.difference(map1, map2);
System.out.println("仅在左侧: " + diff.entriesOnlyOnLeft());
System.out.println("仅在右侧: " + diff.entriesOnlyOnRight());
System.out.println("值不同: " + diff.entriesDiffering());
5. Optional - 避免空指针
java
// 创建 Optional
Optional<String> optional = Optional.of("Hello");
Optional<String> nullable = Optional.fromNullable(null);
Optional<String> absent = Optional.absent();
// 判断是否存在
if (optional.isPresent()) {
System.out.println(optional.get());
}
// 提供默认值
String value = nullable.or("Default");
// 转换
Optional<Integer> length = optional.transform(String::length);
// 与 Java 8 Optional 互转
java.util.Optional<String> javaOptional = optional.toJavaUtil();
Optional<String> guavaOptional = Optional.fromJavaUtil(javaOptional);
6. Preconditions - 前置条件检查
java
public void processUser(String name, int age, List<String> roles) {
// 检查非 null
Preconditions.checkNotNull(name, "姓名不能为空");
// 检查参数条件
Preconditions.checkArgument(age >= 0 && age <= 150,
"年龄必须在 0-150 之间,实际值: %s", age);
// 检查状态
Preconditions.checkState(isInitialized, "服务未初始化");
// 检查索引
Preconditions.checkElementIndex(0, roles.size(), "角色列表");
// 检查位置索引
Preconditions.checkPositionIndex(1, roles.size(), "角色列表");
}
7. Objects 工具
java
// 空值判断
boolean isNull = Objects.equal(null, null); // true
// 哈希码
int hash = Objects.hashCode(obj1, obj2, obj3);
// toString 辅助
String str = MoreObjects.toStringHelper(this)
.add("name", name)
.add("age", age)
.toString();
// 输出: ClassName{name=John, age=30}
// 比较链
int result = ComparisonChain.start()
.compare(this.name, other.name)
.compare(this.age, other.age)
.result();
8. IO 工具
java
// 读取文件
String content = Files.asCharSource(new File("test.txt"), Charsets.UTF_8).read();
// 写入文件
Files.asCharSink(new File("output.txt"), Charsets.UTF_8).write("Hello World");
// 复制文件
Files.copy(sourceFile, targetFile);
// 移动文件
Files.move(sourceFile, targetFile);
// 读取所有行
List<String> lines = Files.readLines(new File("test.txt"), Charsets.UTF_8);
// 关闭流
Closer closer = Closer.create();
try {
InputStream in = closer.register(new FileInputStream("file.txt"));
// 使用流
} catch (Throwable e) {
throw closer.rethrow(e);
} finally {
closer.close();
}
9. 数学工具 (Math)
java
// 整数运算
int gcd = IntMath.gcd(12, 18); // 最大公约数: 6
int mod = IntMath.mod(-5, 3); // 模运算: 1
int pow = IntMath.pow(2, 10); // 幂运算: 1024
// 判断是否为质数
boolean isPrime = IntMath.isPrime(17); // true
// 阶乘
int factorial = IntMath.factorial(5); // 120
// 二项式系数
int binomial = IntMath.binomial(5, 2); // 10
// 浮点数比较
boolean fuzzyEquals = DoubleMath.fuzzyEquals(1.0, 1.0000001, 0.00001);
10. RateLimiter - 限流器
java
// 创建限流器:每秒 5 个许可
RateLimiter limiter = RateLimiter.create(5.0);
// 获取许可(阻塞)
limiter.acquire();
processRequest();
// 获取多个许可
limiter.acquire(3);
// 尝试获取许可(非阻塞)
if (limiter.tryAcquire()) {
processRequest();
} else {
rejectRequest();
}
// 带超时的获取
if (limiter.tryAcquire(1, TimeUnit.SECONDS)) {
processRequest();
}
Maven 依赖
xml
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>32.1.3-jre</version>
</dependency>
总结
Guava 提供了丰富的工具类,涵盖集合、字符串、缓存、IO 等多个方面,能够显著提升 Java 开发效率。建议在项目中合理使用这些工具,减少重复造轮子,提高代码质量和可维护性。
关键优势:
- 线程安全的不可变集合
- 强大的集合扩展(Multimap、Table、BiMap)
- 简洁的字符串处理
- 高性能本地缓存
- 完善的前置条件检查
- 实用的限流和数学工具
通过掌握这些常用工具包,你可以写出更加简洁、高效、健壮的 Java 代码。