介绍
Guava: Google Core Libraries for Java
Guava是一个核心Java类库,包含新的集合类型(比如multimap, multiset),不可变集合,图形库,函数类型,内存缓存,并发,I/O,哈希运算,原始类型,反射,字符串处理等方面的内容
下载:https://github.com/google/guava/wiki/Release23
具体最新版本以官网为准
使用参见:User Guide
基础
避免使用null
https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained
集合框架
作为对JDK集合框架的扩展
不可变集合/Immutable collections
"抵御性编程", 避免不经意的修改。将错误抵御在成功构建之前。
Immutable Collection的优点
- 对不信任的库可安全使用
- 线程安全
- 效率更高,不需要支持修改操作
- 相对于JDK内置的Collections.unmodifiableXXX而言,更安全也更有效率
如何创建Immutable Collection
- 使用copyOf(set)
- 使用of(...)
- 使用Builder
public static final ImmutableSet<Color> GOOGLE_COLORS =
ImmutableSet.<Color>builder()
.addAll(WEBSAFE_COLORS)
.add(new Color(0, 191, 255))
.build();
新集合
JDK不能够表述的集合,比如multisets, multimap,tables, bidirectional maps。
注意,所有Guava库扩展的JDK集合类型都遵守JDK的集合协议:即equals, Comparator, hashCode方法的使用时一致的。
Multiset
主要特点:支持同一个元素的多次存储,能够进行一些有效的数字统计
方法 | 描述 |
---|---|
count(E) | 返回元素的次数 |
elementSet() | 返回不重复的元素集合,返回类型时Set<E> |
entrySet() | Similar to Map.entrySet(), returns a Set<Multiset.Entry<E>>, containing entries supporting getElement() and getCount(). |
add(E, int) | 添加元素,同时指定次数 |
remove(E, int) | 移除元素,同时指定次数 |
setCount(E, int) | 设置元素的次数 |
size() | 返回所有元素的出现次数,包括重复的 |
此外,Guava还包括一个SortedMultiset接口,TreeMultiset实现了该接口。
Multimap
很多Java程序员都曾经操作过这样的结构:Map<String,Set<Integer>>, Map<String,List<Integer>>
这非常繁琐,因为为了添加一个元素,必须先判断其中的集合是否已经被创建。但是使用Multimap可以免去这样的麻烦。
Multimap可以返回一些下面的视图,但并不意味着其中的实现是使用视图的数据类型(比如 Mulitmap.get(s) 可能返回 Set<E>, 但并不意味着Multimap的类型为Map<E,Set<E>>)
- asMap 返回一个Map<E, Collection<V>>
- entries
- keySet
- keys
- values
主要实现类:HashMultimap TreeMultimap
BiMap
支持从key-value之间的相互映射, 比如有时候有需要将String转换成Integer,同时使用Integer查询String
使用Map实现如下:
Map<String, Integer> nameToId = Maps.newHashMap();
Map<Integer, String> idToName = Maps.newHashMap();
nameToId.put("Bob", 42);
idToName.put(42, "Bob");
// what happens if "Bob" or 42 are already present?
// weird bugs can arise if we forget to keep these in sync...
但是这种实现有缺点。使用BiMap实现如下:
BiMap<String, Integer> userId = HashBiMap.create();
...
String userForId = userId.inverse().get(id);
- BiMap支持inverse()方法来获取反向映射
- 保证values()返回的值是单一的
主要实现类:HashBiMap
Table
当你使用多键值映射时,你可能会使用 Map<FirstName, Map<LastName, Address>>这样的结构, 这也相当不好使用。使用Table你可以避免这种不方便。
Table实质上是一个两级键(它也只支持两级键)的Map, Table<R,C,V>可以被视为Map<R,Map<C,V>>来使用。
Table<DateOfBirth, LastName, PersonalRecord> records = HashBasedTable.create();
records.put(someBirthday, "Schmo", recordA);
records.put(someBirthday, "Doe", recordB);
records.put(otherBirthday, "Doe", recordC);
records.row(someBirthday); // returns a Map mapping "Schmo" to recordA, "Doe" to recordB
records.column("Doe"); // returns a Map mapping someBirthday to recordB, otherBirthday to recordC
在概念上,Table<R,C,V> 包含row, column两个键值,可以想象成一个二元函数,如果你要定位一个点,必须提供x,y, 通过 z=f(x,y)即可获得该点的值。
- rowMap 返回 Map<FirstName, Map<LastName, Address>>
- row(r) 返回 Map<C,V>
- column(c) 返回Map<R,V>
- cellSet() 返回 Colelction<Cell<R,C,V>>
主要实现类:HashBasedTable TreeBasedTable ArrayTable
RangeSet
提供对区间的表达,比如 [3,4) 可以表达为 closedOpen(3,4)
RangeSet<Integer> rangeSet = TreeRangeSet.create();
rangeSet.add(Range.closed(1, 10)); // {[1, 10]}
rangeSet.add(Range.closedOpen(11, 15)); // disconnected range: {[1, 10], [11, 15)}
rangeSet.add(Range.closedOpen(15, 20)); // connected range; {[1, 10], [11, 20)}
rangeSet.add(Range.openClosed(0, 0)); // empty range; {[1, 10], [11, 20)}
rangeSet.remove(Range.open(5, 10)); // splits [1, 10]; {[1, 5], [10, 10], [11, 20)}
RangeMap
RangeMap<Integer, String> rangeMap = TreeRangeMap.create();
rangeMap.put(Range.closed(1, 10), "foo"); // {[1, 10] => "foo"}
rangeMap.put(Range.open(3, 6), "bar"); // {[1, 3] => "foo", (3, 6) => "bar", [6, 10] => "foo"}
rangeMap.put(Range.open(10, 20), "foo"); // {[1, 3] => "foo", (3, 6) => "bar", [6, 10] => "foo", (10, 20) => "foo"}
rangeMap.remove(Range.closed(5, 11)); // {[1, 3] => "foo", (3, 5) => "bar", (11, 20) => "foo"}
强大的集合操作工具
java.util.Collections类没能提供的工具
扩展实用工具
当你希望实现一个Iterator时,这部分会使你的工作更加简单
网友评论