讀古今文學網 > 編寫高質量代碼:改善Java程序的151個建議 > 建議140:推薦使用Guava擴展工具包 >

建議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操作),相對來說功能不是非常強大,不再贅述,讀者有興趣可以自行下載源碼研究一番。