首页 » 编写高质量代码:改善Java程序的151个建议 » 编写高质量代码:改善Java程序的151个建议全文在线阅读

《编写高质量代码:改善Java程序的151个建议》建议140:推荐使用Guava扩展工具包

关灯直达底部

说起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操作),相对来说功能不是非常强大,不再赘述,读者有兴趣可以自行下载源码研究一番。