说起Guava(石榴),可能知道它的读者并不多,要是说起Google-collections,相信大部分读者都有所耳闻。2008年Google发布了Google-collections扩展工具包,主要是对JDK的Collection包进行了扩展,2010年Google发布了Guava项目,其中包含了collections、caching、primitives support、concurrency libraries、common annotations、I/O等,这些都是项目编码中的基本工具包,我们大致浏览一下它的主要功能。
(1)Collections
com. google.common.collect包中主要包括四部分:不可变集合(Immutable Collections)、多值Map、Table表和集合工具类。
不可变集合
不可变集合包括ImmutableList、ImmutableMap、ImmutableSet、ImmutableSortedMap、ImmutableSortedSet等,它比不可修改集合(Unmodifiable Collections)更容易使用,效率更高,而且占用的内存更少。示例代码如下:
//不可变列表
ImmutableList<String>list=ImmutableList.of(/"A/",/"B/",/"C/");
//不可变Map
ImmutableMap<Integer, String>map=ImmutableMap.of(1,/"壹/",2,/"贰/",3,/"叁/");
其中的of方法有多个重载,其目的就是为了便于在初始化的时候直接生成一个不可变集合。
多值Map
多值Map比较简单,在JDK中,Map中的一个键对应一个值,在put一个键值对时,如果键重复了,则会覆盖原有的值,在大多数情况下这比较符合实际应用,但有的时候确实会存在一个键对应多个值的情况,比如我们的通讯录,一个人可能会对应两个或三个号码,此时使用JDK的Map就有点麻烦了。在这种情况下,使用Guava的Multimap可以很好地解决问题,代码如下:
//多值Map
Multimap<String, String>phoneBook=ArrayListMultimap.create();
phoneBook.put(/"张三/",/"110/");
phoneBook.put(/"张三/",/"119/");
System.out.println(phoneBook.get(/"张三/"));
输出的结果是一个包含两个元素的Collection,这是一种很巧妙的处理方式,可以方便地解决我们开发中的问题。
Table表
在GIS(Geographic Information System,地理信息系统)中,我们经常会把一个地点标注在一个坐标上,比如把上海人民广场标注在北纬31.23、东经121.48的位置上,也就是说只要给出了准确的经度和纬度就可以进行精确的定位——两个键决定一个值,这在Guava中是使用Table来表示的,示例代码如下:
Table<Double, Double, String>g=HashBasedTable.create();
//定义人民广场的经纬度坐标
g.put(31.23,121.48,/"人民广场/");
//输出坐标点的建筑物
g.get(31.23,121.48);
其实Guava的Table类与我们经常接触的DBRMS表非常类似,可以认为它是一个没有Schema限定的数据表,比如:
//Table,完全类似于数据库表
Table<Integer, Integer, String>user=HashBasedTable.create();
//第一行、第一列的值是张三
user.put(1,1,/"张三/");
//第一行、第二列的值是李四
user.put(1,2,/"李四/");
//第一行第一列是谁
user.get(1,1);
集合工具类
Guava的集合工具类分得比较细,比如Lists、Maps、Sets分别对应的是List、Map、Set的工具类,它们的使用方法比较简单,比如Map的过滤,如下所示。
//姓名、年龄键值对
Map<String, Integer>user=new HashMap<String, Integer>();
user.put(/"张三/",20);
user.put(/"李四/",22);
user.put(/"王五/",25);
//所有年龄大于20岁的人员
Map<String, Integer>filtedMap=Maps.flterValues(user,
new Predicate<Integer>(){
public boolean apply(Integer_age){
return_age>20;
}
});
(2)字符串操作
Guava提供了两个非常好用的字符串操作工具:Joiner连接器和Splitter拆分器。当然,字符串的连接和拆分使用JDK的方法也可以实现,但是使用Guava更简单一些,比如字符串的连接,代码如下所示:
//定义连接符号
Joiner joiner=Joiner.on(/",/");
//可以连接多个对象,不局限于String;如果有null,则跳过
String str=joiner.skipNulls().join(/"嘿/",/"Guava很不错的。/");
Map<String, String>map=new HashMap<String, String>();
map.put(/"张三/",/"普通员工/");
map.put(/"李四/",/"领导/");
//键值之间以/"是/"连接,多个键值以空格分隔
System.out.println(Joiner.on(/"rn/").withKeyValueSeparator(/"是/").join(map));
Joiner不仅能够连接字符串,还能够把Map中的键值对串联起来,比直接输出Map优雅了许多。Splitter是做字符拆分的,使用方法也比较简单,示例代码如下:
String str=/"你好,Guava/";
//以/",/"中文逗号分隔
for(String s:Splitter.on(/",/").split(str)){
System.out.println(s);
}
//按照固定长度分隔
for(String s:Splitter.fixedLength(2).split(str)){
System.out.println(s);
}
注意fixedLength方法,它是按照给定长度进行拆分的,比如在进行格式化打印的时候,一行最大可以打印120个字符,此时使用该方法就非常简单了。
(3)基本类型工具
基本类型工具在primitives包中,是以基本类型名+s的方式命名的,比如Ints是int的工具类,Doubles是double的工具类,注意这些都是针对基本类型的,而不是针对包装类型的。如下代码所示。
intints={10,9,20,40,80};
//从数组中取出最大值
System.out.println(Ints.max(ints));
List<Integer>integers=new ArrayList<Integer>();
//把包装类型的集合转为基本类型数组
ints=Ints.toArray(integers);
Guava还提供了其他操作(如I/O操作),相对来说功能不是非常强大,不再赘述,读者有兴趣可以自行下载源码研究一番。