Lists.newArrayList()和Maps.newHashMap()创建的是可变集合,非不可变容器,直接使用易引发并发或逻辑错误;应依场景选用容量预设、只读封装或替代API。

Lists.newArrayList() 和 Maps.newHashMap() 为什么不能直接当“空集合”用?
它们创建的是可变集合,不是不可变容器。如果你传给 API 或返回给调用方,对方可能意外修改它,引发隐蔽的并发或逻辑错误。
- 需要返回“只读视图”时,必须套一层
ImmutableList.copyOf()或Collections.unmodifiableList() -
Lists.newArrayList()底层仍是ArrayList,有扩容开销;如果已知大小,优先用Lists.newArrayListWithCapacity(10) -
Maps.newHashMap()默认初始容量 16,负载因子 0.75;高频写入小集合时,用Maps.newHashMapWithExpectedSize(5)减少 rehash
Guava 的 Sets.intersection() 返回的是视图,不是新集合
它底层不拷贝元素,而是每次调用 contains() 或遍历时动态计算交集 —— 所以原始集合变了,交集结果也会变,而且不能序列化、不能多线程安全访问。
- 要固化结果,必须显式转成新集合:
ImmutableSet.copyOf(Sets.intersection(a, b)) - 如果 a 或 b 是
ImmutableSet,交集视图性能尚可;但若其中一个是HashSet且含大量元素,每次iterator()都会遍历较小集合并对每个元素查较大集合,O(min(m,n) × cost_of_contains) - 并集
Sets.union()和差集Sets.difference()同理,都是延迟计算视图
Lists.transform() 和 Maps.transformValues() 已被标记为 @Deprecated
从 Guava 21 开始,这两个方法因“容易引发内存泄漏 + 不支持泛型推导”被弃用,编译会警告,运行时行为也不稳定。
- 替代方案统一用
Streams.stream(list).map(...).collect(Collectors.toList())(Java 8+) - 如果坚持用 Guava,改用
Lists.map(list, function)—— 它返回的是实时映射视图,不缓存结果,但要求function是无副作用纯函数 - 注意:视图类方法(如
map、filter)返回的集合不支持add()、remove(),调用会抛UnsupportedOperationException
计算两个 List 的差集(A − B),别直接用 Iterables.filter(a, Predicates.not(Predicates.in(b)))
这个写法看着简洁,但 Predicates.in(b) 在每次判断时都调用 b.contains(),如果 b 是 ArrayList,单次查找是 O(n),整体变成 O(m × n),数据量稍大就卡住。
立即学习“Java免费学习笔记(深入)”;
- 正确做法:先转
b为HashSet或ImmutableSet,再 filter:Set<T> bSet = ImmutableSet.copyOf(b); Lists.newArrayList(Iterables.filter(a, input -> !bSet.contains(input))) - 如果 a、b 都是
List且元素可比较,用排序 + 双指针更省内存,但代码更重 - Guava 没提供原生的 “List 差集” 工厂方法,别指望
Lists.difference()—— 它根本不存在
contains() 这种隐式遍历。









