Google Collection 1.0 增强了对 Java 集合框架的支持

  • Josh Long
  • 晁晓娟

2010 年 1 月 18 日

话题:JavaGoogleDevOps语言 & 开发架构

Google Collections 库,1.0 最终版,2009 年 12 月发布了。你可以在http://code.google.com/p/google-collections/下载它。这个类库是 Google 工程师 Kevin Bourrillion 和 Jared Levy 的智慧结晶。 最近几年由于 Google 工程师如 Doug Lea, Josh Bloch 和 Bob Lee 以及开源社区的贡献,它发展地很快。

Google Collections 库希望扩展 Java 平台的内建集合库。JDK 集合库——目前属于 java.util.* 包中。它主要包括如下一组接口:java.util.Collection (超接口)、java.util.Set、java.util.SortedSet、java.util.Map、和 java.util.List 等。这些接口直接决定了跟着 JDK 打包发送的各种实现机制互相之间的协议关系。java.util.Set 模糊地定义了一组无序且唯一的元素集合。 java.util.SortedSet 则描述了一组有序且唯一元素集合。

java.util.Map 定义了一个键值的联合——通常在其他语言中称为字典(dictionary),java.util.List 定义了一个有序的集合,而其元素的基数是变化的。最初的框架是由 Josh Bloch 在 Sun 工作时定义的,围绕三个方面进行:接口,实现(抽象和实际)以及允许你扩展操作集合的算法。这些接口被介绍为早期 JDK 提供的类(如 java.util.Vector, java.util.Hashset 等)的彻底改进。Josh Bloch 在 2008 Google Techcast 表明 Google Collections Library 开发的方式让他感觉良好。

Google Collections 库也提供了新的工具实现方法和一组关注并发的类库,其中包括不可变集合的实现。“不可变” 保证了系统中没有其他的因素能改变集合的状态,即使是该实现本身。而“不可修改” (就像 JDK 的 java.util.Collections 类的不可修改的工厂方法)只是保证集合的客户端 / 用户永远不能改变集合。通常,这些实现不是 JDK 封装器,而是通过适度地调节,更多地考虑内存来重新实现接口。Google Collections 库提供了很多静态工厂方法和程序来创建对象。有时候这些是颠覆冗余类型声明的简单工具方法。

import com.google.common.collect.*;

...

HashSet<String> hashSet = Sets.newHashSet();

LinkedHashSet<String> linkedHashSet = Sets.newLinkedHashSet();

ArrayList<String> arrayList = Lists.newArrayList();

LinkedList<String> linkedList = Lists.newLinkedList();

其他时候,使用静态工厂方法或程序是因为实现工具没有公开的构造函数。很多场合下并不期望创建子类,因为这要求子类接受不可变协议。在 Google Collections 库中的 Immutable* 接口告诉客户端该集合是保证不可变的,并且实现了它们的 JDK 基本接口协议的语义。可能的情况下集合的用户需要给 Immutable* 接口传递引用。

import com.google.common.collect.*;

...

ImmutableSet<Integer> immutableSet = ImmutableSet.of(1, 2, 3, 4, 5);

ImmutableList<String> immutableList = ImmutableList.of("a,b,c,d,e,f,g".split(","));

该类库也提供了一些唯一的实现方法,包括 MultiMap 和 MultiSet 集合(它们描述了支持查询对象在集合中的基数或频率的集合)。这样,为了保存同一个键关联的多个值,你可能需要用到如下方法:

Multimap<String, Integer> personAndFavoriteNumbers = ArrayListMultimap.create();

personAndFavoriteNumbers.put("josh", 42);

personAndFavoriteNumbers.put("josh", 7);

Collection<Integer>numbers = personAndFavoriteNumbers.get("josh"); // doesn't return Integer

System.out.println(numbers .size()) ; // == 2

注意:get(String) 返回一个键相对应的视图。如果一个键在 map 里没有对应的值,就会返回一个空的集合。如果向该视图集合加入项目,他们就会反映到 Multimap:

Collection<Integer>numbers = personAndFavoriteNumbers.get("josh");

System.out.println(numbers .size()) ; // == 2

numbers.add( 0) ;

System.out.println(numbers .size()) ; // == 3

System.out.println(personAndFavoriteNumbers.get("josh").size() ) ; // == 3

对于各种自定义接口有很多可用的并发实现方法:

ConcurrentHashMultiset<String> concurrentHashMultiset =

ConcurrentHashMultiset.create(Arrays.asList("a,b,c,d,e,f".split(",")));

Google Collections 库通过 com.google.common.base.Predicate 类提供了和各种编程语言协作的友善标签。

import com.google.common.collect.*;



Iterable<Integer> filteredSet = Iterables.filter( someIterable, new Predicate<Integer>(){

public boolean apply( Integer integer) {

return integer > 0 ;

}

}) ;

说起该类库的适用性,Google 有它在生产部署的记录,以及超过 25,000 个详尽测试的单元测试套件。尽管 Google Collections 库看起来非常有前景,但他们也有替代的选择。JDK 的每一次迭代都从新的集合改善有所收获。Apache commons collections 项目也有一些非常有趣的集合实现,而且比该类库出现早很多年,尽管你发现他们并不是泛型友好的。往前看,Kevin Bourrillion 说过该项目的是为了让该类库正式化后并提交给 JCP。

查看英文原文:Google Collections 1.0 Offers Enhanced Implementations of the Java Collections Framework

JavaGoogleDevOps语言 & 开发架构