Java效率提升神器之Guava_第1頁(yè)
Java效率提升神器之Guava_第2頁(yè)
Java效率提升神器之Guava_第3頁(yè)
Java效率提升神器之Guava_第4頁(yè)
Java效率提升神器之Guava_第5頁(yè)
已閱讀5頁(yè),還剩2頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

第Java效率提升神器之Guava目錄JoinerJoiner.MapJoiner源代碼分析拼接Map鍵值對(duì)姊妹篇:Java效率提升神器jOOR

在我們的開(kāi)發(fā)中經(jīng)常會(huì)用到Guava中的一些功能。但是我們所使用到的只是GuavaAPI中的小的可憐的一個(gè)子集。我們大家一起來(lái)發(fā)掘一下Guava中更多的一些功能。

Joiner

這是在我們代碼中出現(xiàn)頻率比較高的一個(gè)功能。經(jīng)常需要將幾個(gè)字符串,或者字符串?dāng)?shù)組、列表之類的東西,拼接成一個(gè)以指定符號(hào)分隔各個(gè)元素的字符串,比如要將一個(gè)用List保存的字符集合拼起來(lái)作為SQL語(yǔ)句的條件,在知道Joiner之前我們會(huì)這樣做。

ArrayListStringconditions=newArrayListString

conditions.add("condition1");

conditions.add("condition2");

conditions.add("condition3");

privateStringbuildCondition(ArrayListStringconditions){

StringBuildersb=newStringBuilder();

for(Stringcondition:conditions){

sb.append(condition);

sb.append("or");

intindex=sb.lastIndexOf("or");

returnindex0sb.substring(0,index):sb.toString();

}//condition1orcondition2orcondition3

基本上會(huì)手寫(xiě)循環(huán)去實(shí)現(xiàn),代碼瞬間變得丑陋起來(lái)。并且循環(huán)完了還得刪除最后一個(gè)多余的or。

使用Guava工具,我們能夠輕而易舉的完成字符串拼接這一簡(jiǎn)單任務(wù)。借助Joiner類,代碼瞬間變得優(yōu)雅起來(lái)。

Joiner.on("or").join(conditions);

被拼接的對(duì)象集,可以是硬編碼的少數(shù)幾個(gè)對(duì)象,可以是實(shí)現(xiàn)了Iterable接口的集合,也可以是迭代器對(duì)象。

除了返回一個(gè)拼接過(guò)的字符串,Joiner還可以在實(shí)現(xiàn)了Appendable接口的對(duì)象所維護(hù)的內(nèi)容的末尾,追加字符串拼接的結(jié)果。

StringBuildersb=newStringBuilder("result:");

Joiner.on("#").appendTo(sb,1,2,3);

System.out.println(sb);//result:1#2#3

我們看下面這個(gè)例子:

Joiner.on("#").join(1,null,3)

如果傳入的對(duì)象中包含空指針,會(huì)直接拋出空指針異常。Joiner提供了兩個(gè)方法,讓我們能夠優(yōu)雅的處理待拼接集合中的空指針。

如果我們希望忽略空指針,那么可以調(diào)用skipNulls方法,得到一個(gè)會(huì)跳過(guò)空指針的Joiner實(shí)例。如果希望將空指針變?yōu)槟硞€(gè)指定的值,那么可以調(diào)用useForNull方法,指定用來(lái)替換空指針的字符串。

Joiner.on("#").skipNulls().join(1,null,3);//1#3

Joiner.on("#").useForNull("").join(1,null,3);//1##3

Joiner.MapJoiner

MapJoiner是Joiner的內(nèi)部靜態(tài)類,用于幫助將Map對(duì)象拼接成字符串。

MapInteger,Integertest=newHashMapInteger,Integer

test.put(1,2);

test.put(3,4);

Joiner.on("#").withKeyValueSeparator("=").join(test);//1=2#3=4

withKeyValueSeparator方法指定了鍵與值的分隔符,同時(shí)返回一個(gè)MapJoiner實(shí)例。

Joiner.on("#").withKeyValueSeparator("=").join(ImmutableMap.of(1,2,3,4));//1=2#3=4

源代碼分析

源碼來(lái)自Guava18.0。Joiner類的源碼一共458行。大部分都是注釋。Joiner只能通過(guò)Joiner.on函數(shù)來(lái)初始化,它的構(gòu)造方法是私有的。

/**

*Returnsajoinerwhichautomaticallyplaces{@codeseparator}betweenconsecutiveelements.

publicstaticJoineron(Stringseparator){

returnnewJoiner(separator);

*Returnsajoinerwhichautomaticallyplaces{@codeseparator}betweenconsecutiveelements.

publicstaticJoineron(charseparator){

returnnewJoiner(String.valueOf(separator));

}

整個(gè)Joiner類最核心的函數(shù)莫過(guò)于AextendsAppendableappendTo(A,Iterator),一切的字符串拼接操作,最后都會(huì)調(diào)用到這個(gè)函數(shù)。這就是所謂的全功能函數(shù),其他的一切appendTo只不過(guò)是它的重載,一切的join不過(guò)是它和它的重載的封裝。

/**

*Appendsthestringrepresentationofeachof{@codeparts},usingthepreviouslyconfigured

*separatorbetweeneach,to{@codeappendable}.

*@since11.0

publicAextendsAppendableAappendTo(Aappendable,Iteratorparts)throwsIOException{

checkNotNull(appendable);

if(parts.hasNext()){

appendable.append(toString(parts.next()));

while(parts.hasNext()){

appendable.append(separator);

appendable.append(toString(parts.next()));

returnappendable;

}

這段代碼的第一個(gè)技巧是使用if和while來(lái)實(shí)現(xiàn)了比較優(yōu)雅的分隔符拼接,避免了在末尾插入分隔符的尷尬;第二個(gè)技巧是使用了自定義的toString方法而不是Object#toString來(lái)將對(duì)象序列化成字符串,為后續(xù)的各種空指針保護(hù)開(kāi)了方便之門(mén)。

來(lái)看一個(gè)比較有意思的appendTo重載。

publicfinalStringBuilderappendTo(StringBuilderbuilder,Iteratorparts){

try{

this.appendTo((Appendable)builder,(Iterator)parts);

returnbuilder;

}catch(IOExceptionvar4){

thrownewAssertionError(var4);

}

在Appendable接口中,append方法是會(huì)拋出IOException的。然而StringBuilder雖然實(shí)現(xiàn)了Appendable,但是它覆蓋實(shí)現(xiàn)的append方法卻是不拋出IOException的。于是就出現(xiàn)了明知不可能拋異常,卻又不得不去捕獲異常的尷尬。

這里的異常處理手法十分機(jī)智,異常變量命名為impossible,我們一看就明白這里是不會(huì)拋出IOException的。但是如果catch塊里面什么都不做又好像不合適,于是拋出一個(gè)AssertionError,表示對(duì)于這里不拋異常的斷言失敗了。

另一個(gè)比較有意思的appendTo重載是關(guān)于可變長(zhǎng)參數(shù)。

publicfinalAextendsAppendableAappendTo(Aappendable,@NullableObjectfirst,@NullableObjectsecond,Object...rest)throwsIOException{

returnthis.appendTo((Appendable)appendable,(Iterable)iterable(first,second,rest));

}

注意到這里的iterable方法,它把兩個(gè)變量和一個(gè)數(shù)組變成了一個(gè)實(shí)現(xiàn)了Iterable接口的集合,非常精妙的實(shí)現(xiàn)!

privatestaticIterableObjectiterable(finalObjectfirst,finalObjectsecond,finalObject[]rest){

Preconditions.checkNotNull(rest);

returnnewAbstractList(){

publicintsize(){

returnrest.length+2;

publicObjectget(intindex){

switch(index){

case0:

returnfirst;

case1:

returnsecond;

default:

returnrest[index-2];

}

要想看明白這段代碼,需要熟悉AbstractList類中迭代器的實(shí)現(xiàn)。迭代器內(nèi)部維護(hù)著一個(gè)游標(biāo),cursor。迭代器的兩大關(guān)鍵操作,hasNext判斷是否還有沒(méi)遍歷的元素,next獲取下一個(gè)元素,它們的實(shí)現(xiàn)是這樣的。

publicbooleanhasNext(){

returncursor!=size();

publicEnext(){

checkForComodification();

try{

Enext=get(cursor);

lastRet=cursor++;

returnnext;

}catch(IndexOutOfBoundsExceptione){

checkForComodification();

thrownewNoSuchElementException();

}

hasNext中關(guān)鍵的函數(shù)調(diào)用是size方法,獲取集合的大小。next方法中關(guān)鍵的函數(shù)調(diào)用是get方法,獲取第i個(gè)元素。Guava的實(shí)現(xiàn)返回了一個(gè)被覆蓋了size和get方法的AbstractList,巧妙的復(fù)用了由編譯器生成的數(shù)組,避免了新建列

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論