Maven 依赖
java
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>33.0.0-jre</version>
</dependency>
第一部分:JDK 无法替代的"独门绝技"
这部分功能是引入 Guava 的主要理由,JDK 原生集合库暂时无法优雅实现。
- Multimap (多值映射)
场景:一个 Key 对应多个 Value(如 Map<String, List>)。
痛点:JDK 原生写法需要繁琐的判空、创建 List、添加元素。
java
// ✅ Guava 写法
// ArrayListMultimap: Value 是 List (允许重复)
// HashMultimap: Value 是 Set (自动去重)
Multimap<String, String> multimap = ArrayListMultimap.create();
// 1. 自动处理容器初始化
multimap.put("Backend", "Java");
multimap.put("Backend", "Go");
multimap.put("Frontend", "Vue");
// 2. 获取集合 (返回 List 或 Set)
Collection<String> list = multimap.get("Backend");
// 输出: [Java, Go]
// 3. 转换为标准 Map
Map<String, Collection<String>> standardMap = multimap.asMap();
- BiMap (双向映射)
场景:Key 和 Value 一一对应,需要通过 Value 反查 Key。
痛点:JDK 需要维护两个 Map,容易导致数据不一致。
java
// ✅ Guava 写法
BiMap<String, Integer> userIdMap = HashBiMap.create();
// 1. 强制 Value 唯一性 (如果 Value 重复会抛异常)
userIdMap.put("Alice", 1001);
userIdMap.put("Bob", 1002);
// 2. 正向查
Integer id = userIdMap.get("Alice"); // 1001
// 3. 反向查 (核心功能)
String name = userIdMap.inverse().get(1002); // "Bob"
// 4. 强制覆盖 (如果 Value 已存在,踢掉旧的 Key)
userIdMap.forcePut("Charlie", 1001); // Alice 被移除
- Table (二维表)
场景:需要两个 Key 确定一个 Value(如 Map<Row, Map<Col, Val>>)。
痛点:JDK 写法嵌套层级深,判空逻辑极其复杂。
java
// ✅ Guava 写法
Table<String, String, Integer> table = HashBasedTable.create();
// 1. 写入 (行, 列, 值)
table.put("ClassA", "Math", 90);
table.put("ClassA", "English", 85);
table.put("ClassB", "Math", 60);
// 2. 读取
Integer score = table.get("ClassA", "Math");
// 3. 行切片 (获取 ClassA 的所有成绩)
Map<String, Integer> rowMap = table.row("ClassA");
// {Math=90, English=85}
// 4. 列切片 (获取所有班级的 Math 成绩)
Map<String, Integer> colMap = table.column("Math");
// {ClassA=90, ClassB=60}
- Guava Cache (本地缓存,很少使用)
场景:单机轻量级缓存,需要自动过期、LRU 淘汰。
注意:高性能场景建议使用 Caffeine(API 与 Guava 几乎一致,性能更强)。
java
// ✅ Guava 写法
LoadingCache<String, User> userCache = CacheBuilder.newBuilder()
.maximumSize(1000) // 容量限制 (LRU)
.expireAfterWrite(10, TimeUnit.MINUTES) // 写入后过期
.recordStats() // 开启统计
.build(new CacheLoader<String, User>() {
@Override
public User load(String key) {
return db.getUser(key); // 缓存击穿时的加载逻辑
}
});
// 使用
User user = userCache.get("u1001");
- RateLimiter (单机限流)
场景:接口防刷、第三方 API 调用频率限制。
java
// ✅ Guava 写法
// 每秒生成 5 个令牌 (QPS = 5)
RateLimiter limiter = RateLimiter.create(5.0);
// 阻塞获取
limiter.acquire();
doBusiness();
// 非阻塞获取 (尝试抢一下,抢不到就算了)
if (limiter.tryAcquire()) {
doBusiness();
} else {
return "系统繁忙";
}
第二部分:工具类增强 (比 JDK 更好用)
- String 处理 (Splitter)
痛点:JDK 的 String.split 会保留尾部空串,且无法自动去除空格。
java
String str = " a, ,b, c,,";
// ❌ JDK 写法
String[] split = str.split(",");
// 结果包含空格和空串,处理麻烦
// ✅ Guava 写法
List<String> list = Splitter.on(",")
.trimResults() // 去除两端空格
.omitEmptyStrings() // 去除空串
.splitToList(str);
// 结果: ["a", "b", "c"]
- 集合切分 (Partition)
场景:批量插入数据库,将大 List 切分为小 List。
java
List<Integer> ids = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
// ✅ Guava 写法
// 将 List 切分为大小为 3 的子列表
List<List<Integer>> parts = Lists.partition(ids, 3);
// 结果: [[1, 2, 3], [4, 5, 6], [7]]
- 集合运算 (Sets)
场景:计算交集、并集、差集。
java
Set<Integer> s1 = Sets.newHashSet(1, 2, 3);
Set<Integer> s2 = Sets.newHashSet(3, 4, 5);
// ✅ Guava 写法
Sets.difference(s1, s2); // 差集: [1, 2]
Sets.intersection(s1, s2); // 交集: [3]
Sets.union(s1, s2); // 并集: [1, 2, 3, 4, 5]
第三部分:已被 JDK 8+ 替代的特性 (迁移指南)
原则:以下功能 Guava 虽然提供,但 JDK 8+ 原生实现已经足够好,新代码请直接使用 JDK。
- 字符串连接 (Joiner)
Guava: Joiner.on(",").join(list)
JDK 8+ (推荐):
java
// 场景 1: 简单的 String join
String result = String.join(",", "a", "b", "c");
// 场景 2: List 转 String
String result = list.stream().collect(Collectors.joining(","));
注:如果需要 skipNulls 功能,Guava 的 Joiner 依然有优势,JDK 需要 filter(Objects::nonNull)。
- 空值处理 (Optional)
Guava: com.google.common.base.Optional (已过时)
JDK 8+ (推荐):
java
Optional<User> opt = Optional.ofNullable(user);
User u = opt.orElse(new User());
- 列表转换 (Lists.transform)
Guava: Lists.transform(list, func) (懒加载,有坑)
JDK 8+ (推荐):
java
List<String> names = users.stream()
.map(User::getName)
.collect(Collectors.toList());
- 基础集合创建
Guava: Lists.newArrayList(), Maps.newHashMap()
JDK 7+ (推荐):
java
// 菱形语法,无需 Guava 工具类
List<String> list = new ArrayList<>();
- 不可变集合 (Immutable Collections)
Guava: ImmutableList.of("A", "B")
JDK 9+ (推荐):
java
// 语法更简洁,且 JVM 层面优化更好
List<String> list = List.of("A", "B");
Set<String> set = Set.of("A", "B");
Map<String, Integer> map = Map.of("k1", 1, "k2", 2);
区别:JDK 的 List.of 对 null 检查更严格,且不提供 Builder 模式。如果需要 Builder 模式构建复杂不可变集合,依然推荐 Guava。
- 时间处理
Guava: 不涉及
JDK 8+ (推荐): 彻底放弃 Date 和 Calendar,全面拥抱 java.time 包 (LocalDateTime, ZonedDateTime, Duration)。