| name | guava-patterns |
| description | Google Guava 最佳实践模式。从官方 wiki 提炼,覆盖 Immutable集合的 of/copyOf/builder 三模式与防御性拷贝规则、Cache 选择决策(LoadingCache vs Cache vs Caffeine)、Joiner/Splitter 不可变流水线、CharMatcher 替代正则、Preconditions 格式化消息校验、CaseFormat 命名互转。
纠正 LLM 误用:手写不可变集合、ConcurrentHashMap 替代 Cache、不知 CharMatcher。
|
| license | Apache-2.0 |
Google Guava 最佳实践模式
来源: Guava Wiki | GitHub: google/guava
Capability Boundaries
✅ Strong Suits
- Immutable集合三模式 —
of()静态常量 / copyOf()防御性拷贝 / builder()渐进构建
- Cache模式选择 — Cache(无默认加载) vs LoadingCache(有默认加载函数) vs Caffeine(高性能)
- Joiner/Splitter流水线 — 函数式组合,实例线程安全可作 static final 常量
- CharMatcher — 预定义字符类操作,比正则更可读更安全
- Preconditions — checkArgument/checkNotNull/checkState 三剑客,格式化消息(类似printf)
- CaseFormat — LOWER_CAMEL/UPPER_UNDERSCORE 等 ASCII 命名风格互转
❌ Out of Scope
- ListenableFuture → 已被 Java8 CompletableFuture 替代,不要再用
- EventBus → 仅进程内,跨服务用 kafka-patterns
- 高性能缓存 → caffeine-patterns(API兼容Guava,性能更好)
核心模式
模式 1: Immutable 集合三选择
public static final ImmutableSet<String> COLORS = ImmutableSet.of("red","green","blue");
class Foo {
final ImmutableSet<Bar> bars;
Foo(Set<Bar> bars) { this.bars = ImmutableSet.copyOf(bars); }
}
ImmutableSet<Color> colors = ImmutableSet.<Color>builder()
.addAll(WEBSAFE_COLORS).add(new Color(0,191,255)).build();
模式 2: Cache 选择决策
有明确的"未命中→加载"函数 → LoadingCache (get(key)自动加载)
加载函数因key而异 → Cache (get(key, callable)每次指定)
高频+高并发+追求性能 → Caffeine (API兼容,窗口TinyLFU)
多实例共享 → Redis
LoadingCache<String, User> cache = CacheBuilder.newBuilder()
.maximumSize(1000).expireAfterWrite(10, TimeUnit.MINUTES)
.build(new CacheLoader<>() { public User load(String k) { return loadDB(k); }});
User u = cache.get("user:1");
LoadingCache<String, Config> cfg = CacheBuilder.newBuilder()
.refreshAfterWrite(1, TimeUnit.MINUTES)
.build(new CacheLoader<>() { public Config load(String k) { ... }});
RemovalListener<String, Conn> listener = RemovalListeners.asynchronous(
notif -> notif.getValue().close(), executor);
模式 3: Joiner/Splitter 不可变流水线
private static final Joiner JOINER = Joiner.on(",").skipNulls();
JOINER.join(list);
Joiner.on("; ").useForNull("N/A").join("a",null,"c");
List<String> parts = Splitter.on(',').trimResults()
.omitEmptyStrings().splitToList("foo,bar,, qux");
Map<String,String> m = Splitter.on('&')
.withKeyValueSeparator('=').split("id=123&name=foo");
Splitter.fixedLength(3).splitToList("abcdefg");
模式 4: CharMatcher 替代正则
CharMatcher.digit().retainFrom("abc123");
CharMatcher.javaIsoControl().removeFrom(string);
CharMatcher.whitespace().trimAndCollapseFrom(" foo bar ", ' ');
CharMatcher.inRange('a','z').or(CharMatcher.is('_')).matchesAllOf(input);
模式 5: Preconditions vs Objects
checkNotNull(obj, "参数不能为空: %s", userId);
checkArgument(age > 0, "年龄必须>0: %s", age);
Objects.requireNonNull(obj, "参数不能为空");
Gotchas
- ImmutableList.of() 不接受 null — 含null抛NPE,需null用Collections.unmodifiableList
- Cache.get() 加载异常抛 ExecutionException — 需要try-catch或getUnchecked()
- expireAfterAccess vs expireAfterWrite — access适合频繁读(会话),write适合稳定数据
- refreshAfterWrite 必须小于 expireAfterWrite — 否则刷新在过期后执行,无意义
- Guava Reflect/ListenableFuture 已被 JDK 替代 — Java8+ 不要再用Guava版本
- Caffeine 性能优于 Guava Cache — 新项目优先Caffeine,仅旧项目兼容用Guava
- CharMatcher 只匹配单个字符 — 多字符模式(如关键词匹配)仍需正则
Data Privacy
本技能不收集、存储或传输任何用户数据。