2017-05-05 62 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();