欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java效率提升神器之Guava-Joiner

 更新時間:2022年07月07日 11:34:51   作者:??你呀不牛??  
這篇文章主要介紹了Java效率提升神器之Guava-Joiner,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下

姊妹篇:Java效率提升神器jOOR

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

Joiner

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

ArrayList<String> conditions = new ArrayList<String>();
conditions.add("condition1");
conditions.add("condition2");
conditions.add("condition3");

private String buildCondition(ArrayList<String> conditions) {
    StringBuilder sb = new StringBuilder();
    for (String condition : conditions) {
        sb.append(condition);
        sb.append(" or ");
    }
    int index = sb.lastIndexOf(" or ");
    return index > 0 ? sb.substring(0, index) : sb.toString();
}  // condition1 or condition2 or condition3

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

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

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

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

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

StringBuilder sb = new StringBuilder("result:");
Joiner.on("#").appendTo(sb, 1, 2, 3);
System.out.println(sb);     //result:1#2#3

我們看下面這個例子:

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

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

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

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 對象拼接成字符串。

 Map<Integer, Integer> test = new HashMap<Integer, Integer>();
 test.put(1, 2);
 test.put(3, 4);
 Joiner.on("#").withKeyValueSeparator("=").join(test); //1=2#3=4

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

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

源代碼分析

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

/**
* Returns a joiner which automatically places {@code separator} between consecutive elements.
*/
public static Joiner on(String separator) {
	return new Joiner(separator);
}
/**
* Returns a joiner which automatically places {@code separator} between consecutive elements.
*/
public static Joiner on(char separator) {
	return new Joiner(String.valueOf(separator));
}

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

/**
   * Appends the string representation of each of {@code parts}, using the previously configured
   * separator between each, to {@code appendable}.
   *
   * @since 11.0
   */
  public <A extends Appendable> A appendTo(A appendable, Iterator<?> parts) throws IOException {
    checkNotNull(appendable);
    if (parts.hasNext()) {
      appendable.append(toString(parts.next()));
      while (parts.hasNext()) {
        appendable.append(separator);
        appendable.append(toString(parts.next()));
      }
    }
    return appendable;
  }

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

來看一個比較有意思的 appendTo 重載。

public final StringBuilder appendTo(StringBuilder builder, Iterator<?> parts) {
    try {
        this.appendTo((Appendable)builder, (Iterator)parts);
        return builder;
    } catch (IOException var4) {
        throw new AssertionError(var4);
    }
}

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

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

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

public final <A extends Appendable> A appendTo(A appendable, @Nullable Object first, @Nullable Object second, Object... rest) throws IOException {
    return this.appendTo((Appendable)appendable, (Iterable)iterable(first, second, rest));
}

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

private static Iterable<Object> iterable(final Object first, final Object second, final Object[] rest) {
    Preconditions.checkNotNull(rest);
    return new AbstractList() {
        public int size() {
            return rest.length + 2;
        }
        public Object get(int index) {
            switch(index) {
            case 0:
                return first;
            case 1:
                return second;
            default:
                return rest[index - 2];
            }
        }
    };
}

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

public boolean hasNext() {
        return cursor != size();
}
public E next() {
        checkForComodification();
    try {
    E next = get(cursor);
    lastRet = cursor++;
    return next;
    } catch (IndexOutOfBoundsException e) {
    checkForComodification();
    throw new NoSuchElementException();
    }
}

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

拼接Map鍵值對

MapJoiner 實現(xiàn)為 Joiner 的一個靜態(tài)內(nèi)部類,它的構(gòu)造函數(shù)和 Joiner 一樣也是私有,只能通過 withKeyValueSeparator來生成實例。類似地,MapJoiner 也實現(xiàn)了 appendTo 方法和一系列的重載,還用 join 方法對 appendTo 做了封裝。

MapJoiner 整個實現(xiàn)和 Joiner 大同小異,在實現(xiàn)中大量使用 Joiner 的 toString 方法來保證空指針保護行為和初始化時的語義一致。

到此這篇關(guān)于Java效率提升神器之Guava-Joiner的文章就介紹到這了,更多相關(guān)Java Guava-Joiner內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別

    關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別

    這篇文章主要介紹了關(guān)于微服務(wù)使用Dubbo設(shè)置的端口和server.port的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • 詳解SpringCloud微服務(wù)架構(gòu)之Hystrix斷路器

    詳解SpringCloud微服務(wù)架構(gòu)之Hystrix斷路器

    本篇文章主要介紹了詳解SpringCloud微服務(wù)架構(gòu)之Hystrix斷路器,Hystrix是一個庫,通過添加延遲容差和容錯邏輯來幫助您控制這些分布式服務(wù)之間的交互,有興趣的可以了解一下
    2018-01-01
  • HashMap之keyset()方法底層原理解讀

    HashMap之keyset()方法底層原理解讀

    這篇文章主要介紹了HashMap之keyset()方法底層原理解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java小程序賽馬游戲?qū)崿F(xiàn)過程詳解

    Java小程序賽馬游戲?qū)崿F(xiàn)過程詳解

    這篇文章主要介紹了Java小程序賽馬游戲?qū)崿F(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-03-03
  • Java可重入鎖的實現(xiàn)原理與應(yīng)用場景

    Java可重入鎖的實現(xiàn)原理與應(yīng)用場景

    今天小編就為大家分享一篇關(guān)于Java可重入鎖的實現(xiàn)原理與應(yīng)用場景,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • 詳解MyBatis工作原理

    詳解MyBatis工作原理

    近來想寫一個mybatis的分頁插件,但是在寫插件之前肯定要了解一下mybatis具體的工作原理吧,本文就詳細總結(jié)了MyBatis工作原理,,需要的朋友可以參考下
    2021-05-05
  • Java synchronized關(guān)鍵字使用方式及特性解析

    Java synchronized關(guān)鍵字使用方式及特性解析

    這篇文章主要介紹了Java synchronized關(guān)鍵字使用方式及特性解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • Java反射之Call stack introspection詳解

    Java反射之Call stack introspection詳解

    這篇文章主要介紹了Java反射之Call stack introspection詳解,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • 詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計

    詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計

    這篇文章主要介紹了詳解spring整合shiro權(quán)限管理與數(shù)據(jù)庫設(shè)計,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-05-05
  • Pulsar源碼徹底解決重復(fù)消費問題

    Pulsar源碼徹底解決重復(fù)消費問題

    這篇文章主要為大家介紹了Pulsar源碼徹底解決重復(fù)消費問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05

最新評論