任何对 JDK 集合框架有经验的程序员都熟悉和喜欢 java.util.Collections 包含的工具方法。Guava 沿着这些路线提供了更多的工具方法:适用于所有集合的静态方法。这是 Guava 最流行和成熟的部分之一。
我们用相对直观的方式把工具类与特定集合接口的对应关系归纳如下:
集合接口 | 属于JDK还是Guava | 对应的Guava工具类 |
---|---|---|
Collection | JDK | Collections2:不要和 java.util.Collections 混淆 |
List | JDK | Lists |
Set | JDK | Sets |
SortedSet | JDK | Sets |
Map | JDK | Maps |
SortedMap | JDK | Maps |
Queue | JDK | Queues |
Multiset | Guava | Multisets |
Multimap | Guava | Multimaps |
BiMap | Guava | Maps |
Table | Guava | Tables |
静态工厂方法
在 JDK 7之前,构造新的范型集合时要讨厌地重复声明范型:
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();
我想我们都认为这很讨厌。因此 Guava 提供了能够推断范型的静态工厂方法:
List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList();
Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();
Guava 的静态工厂方法远不止这么简单。用工厂方法模式,我们可以方便地在初始化时就指定起始元素。
Set<Type> copySet = Sets.newHashSet(elements);
List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");
此外,通过为工厂方法命名(Effective Java 第一条),我们可以提高集合初始化大小的可读性:
List<Type> exactly100 = Lists.newArrayListWithCapacity(100);
List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);
Set<Type> approx100Set = Sets.newHashSetWithExpectedSize(100);
确切的静态工厂方法和相应的工具类一起罗列在下面的章节。
注意:Guava 引入的新集合类型没有暴露原始构造器,也没有在工具类中提供初始化方法。而是直接在集合类中提供了静态工厂方法,例如:
Multiset<String> multiset = HashMultiset.create();
Lists
除了静态工厂方法和函数式编程方法,Lists 为 List 类型的对象提供了若干工具方法。
方法 | 描述 |
---|---|
partition(List, int) | 把 List 按指定大小分割 |
reverse(List) | 返回给定 List 的反转视图。注: 如果 List 是不可变的,考虑改用 ImmutableList.reverse()。 |
List countUp = Ints.asList(1, 2, 3, 4, 5);
List countDown = Lists.reverse(theList); // {5, 4, 3, 2, 1}
List<List> parts = Lists.partition(countUp, 2);//{{1,2}, {3,4}, {5}}
Sets
Sets 工具类包含了若干好用的方法。
集合理论方法
我们提供了很多标准的集合运算(Set-Theoretic)方法,这些方法接受 Set 参数并返回 SetView,可用于:
- 直接当作 Set 使用,因为 SetView 也实现了 Set 接口;
- 用 copyInto(Set) 拷贝进另一个可变集合;
- 用 immutableCopy()对自己做不可变拷贝。
方法 |
---|
union(Set, Set) |
intersection(Set, Set) |
difference(Set, Set) |
symmetricDifference(Set, Set) |
使用范例:
Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
SetView<String> intersection = Sets.intersection(primes,wordsWithPrimeLength);
// intersection包含"two", "three", "seven"
return intersection.immutableCopy();//可以使用交集,但不可变拷贝的读取效率更高
其他 Set 工具方法
方法 | 描述 | 另请参见 |
---|---|---|
cartesianProduct(List<Set>) | 返回所有集合的笛卡儿积 | cartesianProduct(Set...) |
powerSet(Set) | 返回给定集合的所有子集 |
Set<String> animals = ImmutableSet.of("gerbil", "hamster");
Set<String> fruits = ImmutableSet.of("apple", "orange", "banana");
Set<List<String>> product = Sets.cartesianProduct(animals, fruits);
// {{"gerbil", "apple"}, {"gerbil", "orange"}, {"gerbil", "banana"},
// {"hamster", "apple"}, {"hamster", "orange"}, {"hamster", "banana"}}
Set<Set<String>> animalSets = Sets.powerSet(animals);
// {{}, {"gerbil"}, {"hamster"}, {"gerbil", "hamster"}}
Maps
Maps 类有若干值得单独说明的、很酷的方法。
uniqueIndex
Maps.uniqueIndex(Iterable,Function) 通常针对的场景是:有一组对象,它们在某个属性上分别有独一无二的值,而我们希望能够按照这个属性值查找对象——译者注:这个方法返回一个 Map,键为 Function 返回的属性值,值为 Iterable 中相应的元素,因此我们可以反复用这个 Map 进行查找操作。
比方说,我们有一堆字符串,这些字符串的长度都是独一无二的,而我们希望能够按照特定长度查找字符串:
ImmutableMap<Integer, String> stringsByIndex = Maps.uniqueIndex(strings,
new Function<String, Integer> () {
public Integer apply(String string) {
return string.length();
}
});
如果索引值不是独一无二的,请参见下面的 Multimaps.index 方法。
difference
Maps.difference(Map, Map) 用来比较两个 Map 以获取所有不同点。该方法返回 MapDifference 对
象,把不同点的维恩图分解为:
方法 | 说明 |
---|---|
entriesInCommon() | 两个 Map 中都有的映射项,包括匹配的键与值 |
entriesDiffering() | 键相同但是值不同值映射项。返回的 Map 的值类型为 MapDifference.ValueDifference,以表示左右两个不同的值 |
entriesOnlyOnLeft() | 键只存在于左边 Map 的映射项 |
entriesOnlyOnRight() | 键只存在于右边 Map 的映射项 |
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
MapDifference<String, Integer> diff = Maps.difference(left, right);
diff.entriesInCommon(); // {"b" => 2}
diff.entriesInCommon(); // {"b" => 2}
diff.entriesOnlyOnLeft(); // {"a" => 1}
diff.entriesOnlyOnRight(); // {"d" => 5}
网友评论