目录
一、先看清这只工具柜
(一)Guava 的定位与模块全景
(二)与 JDK 赛跑的二十年
(三)引入方式与版本选择
二、集合工具:从"能用"到"用对"
(一)不可变集合:防御性拷贝的终点
1、三种"只读"的本质区别
2、构建方式与 copyOf 的短路优化
3、拒收 null 与设计取舍
(二)列表:拼接、拆分、去重与分片
1、列表与字符串互转
2、去重的三种口径
3、惰性视图:Lists.transform 与 Lists.partition
(三)Map 家族:Multimap、BiMap、Multiset
1、Multimap:一键多值
2、BiMap:双向映射
3、Multiset:会计数的集合
4、Maps 工具:比对、索引与预估容量
(四)集合运算:视图的威力与陷阱
1、交集、并集、差集与对称差
2、视图会"活"着跟随源集合
3、子集、笛卡尔积、幂集与组合
4、业务场景:权限比对与标签同步
三、字符串:Joiner、Splitter、CharMatcher 与 Strings
(一)Joiner:可复用、线程安全的拼接器
(二)Splitter:比 String.split 更诚实
(三)CharMatcher:字符级的筛子
1、先选字符,再定动作
2、零宽字符的陷阱
3、性能提示:precomputed
(四)Strings 与 CaseFormat
(五)一条输入清洗流水线
四、数据流:FluentIterable、Iterables 与 Stream 的分工
(一)惰性求值的本质
(二)FluentIterable 与 Stream 的对照
(三)Iterables 的几把小刀
(四)链式处理的取舍
五、Table:二维映射的利器
(一)结构与视图
(二)四种实现的选型
1、HashBasedTable:通用首选
2、TreeBasedTable:行列有序
3、ArrayTable:稠密矩阵
4、ImmutableTable:构建一次,处处共享
(三)常见误区
1、往 Table 里放 null
2、用嵌套 Table 表达三维数据
3、把 Table 当数据库用
(四)实战:库存矩阵
六、Cache:本地缓存的正确姿势
(一)为什么不是 ConcurrentHashMap
(二)构建与加载
1、两种加载方式
2、加载器不能返回 null
(三)回收策略的真实行为
1、基于容量:近似 LRU 与分段
2、基于权重:淘汰的是最久未用,不是最重
3、基于时间:三种策略的区别
4、基于引用:weakKeys 的身份比较陷阱
5、组合策略的注意事项
(四)统计、监听与移除原因
(五)从 Guava Cache 到 Caffeine
七、EventBus:进程内发布订阅
(一)基本用法
(二)分发语义:同步、队列与异常
1、同步总线的分发顺序
2、异常不会传给调用方
3、线程模型与 AsyncEventBus
(三)官方为何不再推荐
八、工具柜里的其他抽屉
(一)Preconditions 与 Verify
(二)Range、RangeSet 与 RangeMap
(三)RateLimiter 与 Stopwatch
(四)Hashing 与 BloomFilter
(五)ListenableFuture 与并发小工具
九、落地:一张选型清单
(一)JDK 优先还是 Guava 优先
(二)依赖治理:冲突、BOM 与 shading
(三)团队规范与评审清单
十、结语
参考链接
干货分享,感谢您的阅读!
几乎每个 Java 项目里都躺着一个叫StringUtils、CollectionHelper或CommonUtil的类。它们大多从某次"顺手写一个"开始:把列表拼成逗号串,把逗号串拆回列表,给 Map 做个分组,再包一层带过期时间的ConcurrentHashMap当缓存。几年下来,这些类越长越胖,边界条件各写各的:有的吞掉 null,有的抛出 NPE,有的在尾部多出一个空串,有的在并发下加载了五十次数据库。
Google 开源的 Guava 就是为了终结这种局面而生的。它把 Google 内部多年沉淀的基础工具打包成一个库:不可变集合、多值映射、二维表、字符串拆分拼接、字符匹配、本地缓存、事件总线、区间、哈希、限流……几乎覆盖了"写业务代码时总要顺手造的那些轮子"。
但"拿来就用"只是第一步。很多团队用了 Guava 多年,依然会在几个地方反复摔跤:把Sets.intersection的返回值当成快照,往HashBasedTable里放 null,以为maximumSize(100)就一定能装 100 个,用weakKeys()缓存字符串键却永远取不到值,把 EventBus 当成跨模块解耦的银弹。这些问题在示例代码里看不出来,却会在线上悄悄出错。
这次我们换个讲法:每一类工具,先讲清它解决了什么问题,再用可运行的代码给出真实输出,最后把容易被忽略的语义差异和