2016-02-29 108 views

回答

1
private String appendPrefixToEachLine(String prefix, String s) { 
    StringBuilder stringBuilder = new StringBuilder(); 
    new BufferedReader(new StringReader(s)).lines() 
      .map(line -> prefix + line + '\n') 
      .forEach(stringBuilder::append); 
    // Delete last added new line 
    stringBuilder.deleteCharAt(stringBuilder.length() - 1); 
    return stringBuilder.toString(); 
} 
+0

而不是'\ n',你可以使用'System.lineSeparator()'。 –

+0

不错的答案:)让我+1 –

+0

可选的,你可以做'新的StringJoiner(前缀,前缀,“”)',并删除对'地图'的调用。 – flakes

0

您不应在字符串上使用+运算符创建行。这会创建许多不必要的字符串中间实例。当你有一个StringBuilder你可以追加一切吧:

private String appendPrefixToEachLine(String prefix, String s) { 
    StringBuilder stringBuilder = new StringBuilder(); 
    new BufferedReader(new StringReader(s)).lines() 
      .forEach(line -> stringBuilder.append(prefix).append(line).append('\n')); 
    // Delete last added new line 
    stringBuilder.deleteCharAt(stringBuilder.length() - 1); 
    return stringBuilder.toString(); 

}

+0

没关系。由于Java 6中,您可以使用+运算符,因为编译器在内部取代它的StringBuilder的到... – Gaskoin

+0

@Gaskoin但它是每行一个新的StringBuilder ......并不是一开始就创造了一个StringBuilder的。 –

+0

烨,真实,为时已晚,我:) – Gaskoin

5

您可以使用正则表达式

static String appendPrefixToEachLine(String prefix, String s) { 
    String ret = prefix + s.replaceAll("(\r\n|\n)", "$1" + prefix); 
    return ret.substring(0, ret.length() - prefix.length()); 
} 

由于@Holger提到你可以做到这一点没有捕获组

return prefix+s.replaceAll("(?:\r\n?|\n)(?!\\z)", "$0"+Matcher.quoteReplacement(prefix)); 

这个正则表达式说,找到一个新行后的地方,但不是在结束之前。

+3

的情况下模拟线配套的标准行为(如在'BufferedReader'),你应该匹配唯一'\ r'为那么,模式应该是'\ r \ n?| \ n'。请注意,当您使用“$ 0”而不是“$ 1”时,不需要大括号。而且我会用['quoteReplacement']引用'prefix'(https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#quoteReplacement-java.lang.String - )是安全的。如果你追加输入的结束图案的负前瞻:'(?!\ Z)'你不需要'substring'操作。 – Holger

+0

在正则表达式中使用两组会慢很多? '返回前缀+ s。replaceAll(“(\ r \ n | \ n)(。+)”,“$ 1”+前缀+“$ 2”);或者是做一个单独的组替换,然后清理'substring'更好的解决方案? – flakes

+3

@flkes:如上所述,您完全可以在不捕获组的情况下执行:'返回前缀+ s.replaceAll(“(?:\ r \ n?| \ n)(?!\\ z)”,“$ 0” .quoteReplacement(prefix));'但我不希望有明显的性能差异。毕竟,每个组只记录保存开始和结束的“int”,并且正则表达式总是为至少十组预留存储(无论出于何种原因)。最重要的是要复制的'char'的数量,所以不管需要多少个组,最好避免使用'substring'操作。 – Holger

2

您问过一个Java 8解决方案,但没有必要为此使用任何Java 8功能。以下是我想做到这一点:

static String prefixLines(String prefix, String input) { 
    return input.replaceAll(".*\\R|.+\\z", Matcher.quoteReplacement(prefix) + "$0"); 
} 

我想匹配整行(包括部分最后一行)使事情变得比匹配只是行分隔符,如Peter Lawrey's answer更容易一点。不过,+1。此外,荣幸Holger提及quoteReplacement,这是很容易忘记。

请注意,我使用了与任何Unicode换行符匹配的\\R。但是,如果重要,这与BufferedReader.readLine()的行为不符。

0
private String appendPrefixToEachLine(String prefix, String s) { 
    return new BufferedReader(new StringReader(s)).lines() 
     .collect(Collectors.joining('\n'+prefix, prefix, "")); 
} 

说明:收集所有行并用提供的分隔符将它们连接起来。

+0

这出来相当不错:) –