如何为除最后一行之外的所有行追加换行符?

时间:2009-01-15 20:24:29

标签: java foreach newline

我正在迭代HashMap(有关详细信息,请参阅my earlier question)并构建一个由Map中包含的数据组成的字符串。对于每个项目,我将有一个新行,但对于最后一项,我不想要新行。我怎样才能做到这一点?我以为我可以这么检查,看看这个条目是否是最后一个,但我不知道该怎么做。

谢谢!

16 个答案:

答案 0 :(得分:70)

将您的思维过程从“将所有行除了最后一次”添加到“除了第一次之前的所有行中断”:

boolean first = true;
StringBuilder builder = new StringBuilder();

for (Map.Entry<MyClass.Key,String> entry : data.entrySet()) {
    if (first) {
        first = false;
    } else {
        builder.append("\n"); // Or whatever break you want
    }
    builder.append(entry.key())
           .append(": ")
           .append(entry.value());
}

答案 1 :(得分:68)

一种方法(向Jon Skeet道歉,借用他的部分Java代码):

StringBuilder result = new StringBuilder();

string newline = "";  
for (Map.Entry<MyClass.Key,String> entry : data.entrySet())
{
    result.append(newline)
       .append(entry.key())
       .append(": ")
       .append(entry.value());

    newline = "\n";
}

答案 2 :(得分:13)

这个怎么样?

StringBuilder result = new StringBuilder();

for(Map.Entry<MyClass.Key,String> entry : data.entrySet())
{
    builder.append(entry.key())
       .append(": ")
       .append(entry.value())
       .append("\n");
}

return builder.substring(0, builder.length()-1);

道歉并且感谢Jon和Joel从他们的例子中“借用”。

答案 3 :(得分:9)

通常我会使用apache-commons-lang StringUtils#join这些东西。虽然编写所有这些实用程序功能并不是很难,但重用现有的经过验证的库总是更好。 Apache-commons充满了有用的东西!

答案 4 :(得分:4)

如果您使用迭代器而不是...,则每个代码都可能如下所示:

StringBuilder builder = new StringBuilder();

Iterator<Map.Entry<MyClass.Key, String>> it = data.entrySet().iterator();

while (it.hasNext()) {
    Map.Entry<MyClass.Key, String> entry = it.next();

    builder.append(entry.key())
    .append(": ")
    .append(entry.value());

    if (it.hasNext()) {
        builder.append("\n");
    }
}

答案 5 :(得分:3)

这可能是一个更好的例子......

final StringBuilder buf = new StringBuilder();
final String separator = System.getProperty("line.separator"); // Platform new line
for (Map.Entry<MyClass.Key,String> entry: data.entrySet()) {
    builder.append(entry.key())
       .append(": ")
       .append(entry.value())
       .append(separator);
}
// Remove the last separator and return a string to use.
// N.b. this is likely as efficient as just using builder.toString() 
// which would also copy the buffer, except we have 1 char less 
// (i.e. '\n').
final String toUse = builder.substring(0, builder.length()-separator.length()-1);

答案 6 :(得分:2)

这是我的简洁版本,它使用StringBuilder的length属性而不是额外的变量:

StringBuilder builder = new StringBuilder();

for (Map.Entry<MyClass.Key,String> entry : data.entrySet())
{
    builder.append(builder.length() > 0 ? "\n" : "")
           .append(entry.key())
           .append(": ")
           .append(entry.value());
}

(抱歉并感谢Jon和Joel从他们的例子中“借用”。)

答案 7 :(得分:2)

一种解决方案是为StringBuilder创建自定义包装器。它无法扩展,因此需要包装器。

public class CustomStringBuilder {

final String separator = System.getProperty("line.separator");

private StringBuilder builder = new StringBuilder();

public CustomStringBuilder appendLine(String str){
    builder.append(str + separator);
    return this;
}

public CustomStringBuilder append(String str){
    builder.append(str);
    return this;
}

public String toString() {
    return this.builder.toString();
}

}

这样的实施:

CustomStringBuilder builder = new CustomStringBuilder();

//iterate over as needed, but a wrapper to StringBuilder with new line features.

builder.appendLine("data goes here");
return builder.toString();

这确实有一些缺点:

  • 编写通常不以“域/业务”为中心的代码
  • 不使用开源标准解决方案,如:StringUtils.join
  • 强制维护一个包装JDK类的类,这个类是最终的,因此需要长期更新。

我使用StringUtils.join解决方案来迭代集合,甚至在代码中构建轻量级构建方法模式。

答案 8 :(得分:1)

假设你的foreach循环遍历文件,只需在每个字符串中添加一个新行,并在循环退出时删除最后一个新行。

答案 9 :(得分:1)

不确定这是否是最好的,但这是更容易的方法:

循环遍历所有值并将\ n通常附加到stringbuffer中。然后,做这样的事情

sb.setLength(sb.length()-1); 

答案 10 :(得分:0)

这是一个补充分割的连接方法会派上用场的地方,因为那时你可以使用一个新的行作为分隔符加入所有元素,当然它不会在末尾添加一个新行结果;这就是我在各种脚本语言(Javascript,PHP等)中的表现。

答案 11 :(得分:0)

如果您使用Class Separator,则可以

StringBuilder buf = new StringBuilder();
Separator separator = new Separator("\n");
for (Map.Entry<MyClass.Key,String> entry: data.entrySet()) {
    builder.append(separator)
       .append(entry.key())
       .append(": ")
       .append(entry.value());
}

分隔符在首次使用时打印空字符串,在所有后续使用时打印分隔符。

答案 12 :(得分:0)

哈!感谢this post我找到了另一种方法:

public static class Extensions
{
    public static string JoinWith(this IEnumerable<string> strings, string separator)
    {
        return String.Join(separator, strings.ToArray());
    }
}

当然这是在C#中,Java不会(还)支持扩展方法,但你应该能够根据需要进行调整 - 主要是使用String.Join,并且我确信java有一些类比。

另请注意,这意味着要对字符串进行额外的迭代,因为您必须首先创建数组,然后迭代它以构建字符串。此外,你创建数组,其中你可以通过IEnumerable获得一些其他方法,一次只能在内存中保存一个字符串。但我真的很喜欢这种清晰度。

当然,考虑到Extension方法的功能,您可以将任何其他代码抽象为扩展方法。

答案 13 :(得分:0)

让图书馆为你做这件事。

import com.sun.deploy.util.StringUtils;

以及许多其他人都有StringUtils,它有一个join方法。您可以在一行中执行此操作:

StringUtils.join(list, DELIMITER);

但是对于更多上下文,以下是使用hashmap的方法。

public static String getDelimitatedData(HashMap<String, String> data) {
    final String DELIMITER = "\n"; //Should make this a variable
    ArrayList<String> entries = new ArrayList<>();

    for (Map.Entry<String, String> entry : data.entrySet()) {
        entries.add(entry.getKey() + ": " + entry.getValue());
    }

    return StringUtils.join(entries, DELIMITER);
}

答案 14 :(得分:0)

使用加入API的JDK字符串:

String result = data.stream()
    .map((k,v) -> String.format("%s : %s", k, v)
    .collect(Collectors.joining("\n"));

答案 15 :(得分:0)

如果您不关心空格,并且仅当您不打算向trim()追加任何内容时,也可以使用StringBuilder方法来实现此目的。

这是一些示例代码

StringBuilder sb = new StringBuilder();

for (Map.Entry<String,String> entry : myMap.entrySet()) {
    builder.append(entry.key())
           .append(": ")
           .append(entry.value())
           .append("\n");
}
return sb.toString().trim();