2017-05-05 69 views
1

我要重寫以下Java 8代碼是Java 7的兼容:如何使用Java 7模式重寫Java 8流()?

System.out.println("items: " + stringList.stream().collect(Collectors.joining(", "))); 

一個天真的方法是:

System.out.print("items: "); 
String joiner = ""; 
for (String item : stringList) { 
    System.out.print(joiner + item); 
    joiner = ", "; 
} 
System.out.println(); 

有哪些可供選擇的模式來完成這個任務?例如,是否可以使用命令模式以某種方式將print()封裝爲對象?

+0

的StringBuilder .... –

+1

或者乾脆看看在JDK 8 StringJoiner]的源代碼(HTTP ://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/StringJoiner.java)類並編寫它的JDK 7版本 –

+1

你的代碼幾乎沒問題。我唯一想做的改變是分別爲'System.out.print'' joiner'和'item',以避免不必要的字符串創建。 'StringBuilder'在這裏效率較低,因爲你只需要緩衝字符,創建一個字符串,寫入另一個字符緩衝區;相反,直接寫入最終緩衝區(就像你已經做的那樣)。 –

回答

0
StringBuilder sb = new StringBuilder("items: "); 
for (String item : stringList) { 
    sb.append(item).append(", "); 
} 
if (!stringList.isEmpty()) { 
    sb.setLength(sb.length() - 2); 
} 
System.out.println(sb.toString()); 

評論:

  1. StringBuilder與構造函數參數初始化
  2. append返回StringBuilder這樣你就可以把它們連
  3. 最後兩個字符需要刪除,以避免尾隨「 ,「
  4. stringList可能爲空,所以只刪除末尾的逗號如果不是
  5. 這可能會更有效,因爲您可以避免大量臨時String創建和複製。
+1

或者,如果'!sb.isEmpty()',則可以先追加冒號分隔符,然後再追加下一個項目。 –

+0

謝謝。我編輯了我的原始帖子,刪除了循環創建的字符串,因爲它不是我要提請注意的部分。我的問題是如何使用另一種設計模式完成給定的任務。例如,一個將封裝函數作爲變量傳遞的命令模式。 –

2

如果在classpath番石榴(和你真的應該IMO),比它的加盟同樣流暢的方式,而是用JDK-7(很明顯,你需要一個版本番石榴的是JDK兼容-7兼容):

String joined = Joiner.on(",").join(stringList); 
0

幾乎一樣,只是避免串聯:

System.out.print("items: "); 
boolean first = true; 
for (String item : stringList) { 
    if (! first) 
     System.out.print(", "); 
    System.out.print(item); 
    first = false; 
} 
System.out.println(); 

注:布爾的意義就會顛倒,所以我們並不需要用否定,但我更喜歡它是wa爲了便於閱讀。

0

請注意,您最初的Java 8碼

System.out.println("items: " + stringList.stream().collect(Collectors.joining(", "))); 

可以簡化爲

System.out.println("items: " + String.join(", ", stringList)); 

在Java 7,你將不得不使用一個StringBuilder有效地做同樣的,但你可以封裝它在一個實用程序類中,類似於Java 8的StringJoiner。使用具有相同API的類可以創建Java 7兼容的代碼,這些代碼仍然可以輕鬆適應使用Java 8的代碼。

然而,這是相當不可能的,這是你的應用程序的性能最關鍵的部分,因此,你可以使用一個務實的做法:

String s = stringList.toString(); 
System.out.append("items: ").append(s, 1, s.length()-1).println(); 

這根本不打印字符串的[]表示,從而產生所需的逗號分隔列表。雖然這個字符串表示沒有強制要求,但是很難找到一個不遵守這個約定的有用集合實現的例子(並且你會知道你是否使用了這樣的類)。

關於你提到的類似「命令模式」的更新問題,好吧,你不需要對你的問題的Stream代碼做任何事情,但已經有抽象了,就像上面代碼中使用的那樣。

你就可以創建

static <A extends Appendable> A join(A target, CharSequence sep, List<?> data) { 
    try { 
     CharSequence currSep = ""; 
     for(Object item: data) { 
      target.append(currSep).append(item.toString()); 
      currSep = sep; 
     } 
     return target; 
    } catch(IOException ex) { 
     throw new IllegalStateException(ex); 
    } 
} 

的方法,它提供了一些靈活性,例如你可以用它來獲取String

String s = join(new StringBuilder(), ", ", stringList).toString(); 
System.out.println("items: " + s); 

或只是打印:

join(System.out.append("items: "), ", ", stringList).println();