1. 介绍

本文档采用精炼的代码片段和实用案例形式,整理了Guava集合库的核心用法。

格式是持续更新的代码示例集,无需冗长说明——目的是在开发中快速查阅API的常见操作模式。

2. 实用代码片段

2.1 将 List 转换为 List

注意:这是解决Java泛型集合非协变问题的变通方案

class CastFunction<F, T extends F> implements Function<F, T> {
    @Override
    public final T apply(final F from) {
        return (T) from;
    }
}
List<TypeParent> originalList = Lists.newArrayList();
List<TypeChild> theList = Lists.transform(originalList, 
    new CastFunction<TypeParent, TypeChild>());

2.2 不使用Guava的简单替代方案(涉及两次类型转换)

List<Number> originalList = Lists.newArrayList();
List<Integer> theList = (List<Integer>) (List<? extends Number>) originalList;

2.3 将 Iterable 添加到集合中

Iterable<String> iter = Lists.newArrayList();
Collection<String> collector = Lists.newArrayList();
Iterables.addAll(collector, iter);

2.4 根据自定义规则检查集合是否包含元素

Iterable<String> theCollection = Lists.newArrayList("a", "bc", "def");
    boolean contains = Iterables.any(theCollection, new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
        return input.length() == 1;
    }
});
assertTrue(contains);

2.5 使用搜索的替代方案

Iterable<String> theCollection = Sets.newHashSet("a", "bc", "def");
boolean contains = Iterables.find(theCollection, new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
       return input.length() == 1;
    }
}) != null;
assertTrue(contains);

2.6 仅适用于 Set 的替代方案

Set<String> theCollection = Sets.newHashSet("a", "bc", "def");
boolean contains = !Sets.filter(theCollection, new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
        return input.length() == 1;
    }
}).isEmpty();
assertTrue(contains);

2.7 Iterables.find 未找到元素时抛出 NoSuchElementException

Iterable<String> theCollection = Sets.newHashSet("abcd", "efgh", "ijkl");
Predicate<String> inputOfLengthOne = new Predicate<String>() {
    @Override
    public boolean apply(final String input) {
        return input.length() == 1;
    }
};
String found = Iterables.find(theCollection, inputOfLengthOne);

❌ 这将抛出 NoSuchElementException 异常

java.util.NoSuchElementException
    at com.google.common.collect.AbstractIterator.next(AbstractIterator.java:154)
    at com.google.common.collect.Iterators.find(Iterators.java:712)
    at com.google.common.collect.Iterables.find(Iterables.java:643)

解决方案:使用重载的 find 方法,传入默认返回值:

String found = Iterables.find(theCollection, inputOfLengthOne, null);

2.8 从集合中移除所有 null 值

List<String> values = Lists.newArrayList("a", null, "b", "c");
Iterable<String> withoutNulls = Iterables.filter(values, Predicates.notNull());

2.9 直接创建不可变 List/Set/Map

ImmutableList<String> immutableList = ImmutableList.of("a", "b", "c");
ImmutableSet<String> immutableSet = ImmutableSet.of("a", "b", "c");
ImmutableMap<String, String> imuttableMap = 
    ImmutableMap.of("k1", "v1", "k2", "v2", "k3", "v3");

2.10 从标准集合创建不可变集合

List<String> muttableList = Lists.newArrayList();
ImmutableList<String> immutableList = ImmutableList.copyOf(muttableList);

Set<String> muttableSet = Sets.newHashSet();
ImmutableSet<String> immutableSet = ImmutableSet.copyOf(muttableSet);

Map<String, String> muttableMap = Maps.newHashMap();
ImmutableMap<String, String> imuttableMap = ImmutableMap.copyOf(muttableMap);

2.11 使用构建器的替代方案

List<String> muttableList = Lists.newArrayList();
ImmutableList<String> immutableList = 
    ImmutableList.<String> builder().addAll(muttableList).build();

Set<String> muttableSet = Sets.newHashSet();
ImmutableSet<String> immutableSet = 
    ImmutableSet.<String> builder().addAll(muttableSet).build();

Map<String, String> muttableMap = Maps.newHashMap();
ImmutableMap<String, String> imuttableMap = 
    ImmutableMap.<String> builder().putAll(muttableMap).build();

3. 更多 Guava 编程手册

Guava 是个功能全面且极其实用的库——这里还有几个以编程手册形式介绍的 API:

享受编码乐趣吧。

4. 后续计划

如开头所述,我正在尝试这种不同的格式——编程手册,旨在将使用 Guava 集合的常见任务汇集一处。这种格式注重简洁高效,因此大多数配方只有代码示例,无需额外解释

最后——我将本文视为持续更新的文档——遇到新配方和示例时会不断补充。欢迎在评论区提供更多内容,我会将其纳入手册。

所有示例代码的实现可以在 GitHub 上找到——这是一个基于 Maven 的项目,可以直接导入运行。


原始标题:Guava Collections Cookbook