在java中增强for循环的最后一次迭代

Mer*_*ous 134 java foreach for-loop conditional-execution

有没有办法确定循环是否最后一次迭代.我的代码看起来像这样:

int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();

for(int i : array)
{
    builder.append("" + i);
    if(!lastiteration)
        builder.append(",");
}
Run Code Online (Sandbox Code Playgroud)

现在问题是我不想在最后一次迭代中附加逗号.现在有一种方法可以确定它是最后一次迭代还是我坚持使用for循环或使用外部计数器来跟踪.

Jon*_*eet 220

另一种方法是在追加i之前附加逗号,而不是在第一次迭代时.(请不要使用"" + i,顺便说一下 - 你真的不想在这里连接,而且StringBuilder有一个非常好的追加(int)重载.)

int[] array = {1, 2, 3...};
StringBuilder builder = new StringBuilder();

for (int i : array) {
    if (builder.length() != 0) {
        builder.append(",");
    }
    builder.append(i);
}
Run Code Online (Sandbox Code Playgroud)

关于这一点的好处是它可以与任何Iterable东西一起工作- 你不能总是索引东西.(当你真正使用StringBuilder时,"添加逗号然后将其删除"是一个很好的建议 - 但它不适用于写入流等内容.虽然这可能是解决这个问题的最佳方法. )

  • @Liverpool(等):1000次不必要的检查非常,*非常*不太可能对性能产生任何重大影响.我可能同样指出Dinah的解决方案添加的额外字符*可能*导致StringBuilder必须扩展,使(cont)最终字符串的大小加倍 (3认同)
  • 此外,我的解决方案是更普遍适用的解决方案,因为它只依赖于能够编写.您可以采用我的解决方案并将其更改为写入流等 - 之后您可能无法收回不必要的数据.我喜欢通常适用的模式. (3认同)
  • 良好的模式,但builder.length()!= 0是脆弱的 - 想象一下在循环之前将某些东西(有条件地!)添加到缓冲区.相反,使用`isFirst`布尔标志.奖金:也快. (2认同)
  • @Jason:我当然使用"isFirst"模式,其中构建器在第一次迭代时不会为空.但是,当它不需要时,根据我的经验,它会给实现增加相当大的膨胀. (2认同)
  • 不必要的缓冲空间 但重要的是可读性.我碰巧发现我的版本比Dinah更具可读性.如果你有相反的感觉,那很好.在找到瓶颈之后,我只会考虑不必要的"ifs"对性能的影响. (2认同)

too*_*kit 143

另一种方法:

String delim = "";
for (int i : ints) {
    sb.append(delim).append(i);
    delim = ",";
}
Run Code Online (Sandbox Code Playgroud)

更新:对于Java 8,您现在拥有收集器

  • @Bill:这不是一个坚硬而快速的规则; 有时"聪明"的解决方案是"更正确"的解决方案.更重要的是,你真的觉得这个版本难以阅读吗?无论哪种方式,维护者都需要逐步完成它 - 我不认为差异是显着的. (8认同)

Din*_*nah 39

总是追加可能更容易.然后,当你完成循环时,只需删除最后一个字符.通过这种方式减少条件.

您可以使用索引为StringBuilder的sdeleteCharAt(int index)length() - 1

  • 也许是我,但我真的不喜欢你正在删除你刚才添加的东西...... (9认同)
  • 这个问题最有效的解决方案.+1. (5认同)
  • Fortega:我不喜欢每次都会检查99%的时间.应用Dinah或sblundy的解决方案似乎更合乎逻辑(并且更快). (2认同)

Oma*_*eji 31

也许你正在使用错误的工具来完成工作.

这比你正在做的更加手动,但如果不是有点"旧学校",它会更优雅

 StringBuffer buffer = new StringBuffer();
 Iterator iter = s.iterator();
 while (iter.hasNext()) {
      buffer.append(iter.next());
      if (iter.hasNext()) {
            buffer.append(delimiter);
      }
 }
Run Code Online (Sandbox Code Playgroud)


Phi*_*l H 15

这几乎是StackOverflow问题的重复.你想要的是StringUtils,并调用join方法.

StringUtils.join(strArr, ',');
Run Code Online (Sandbox Code Playgroud)


bru*_*nde 14

另一种解决方案(也许效率最高)

    int[] array = {1, 2, 3};
    StringBuilder builder = new StringBuilder();

    if (array.length != 0) {
        builder.append(array[0]);
        for (int i = 1; i < array.length; i++ )
        {
            builder.append(",");
            builder.append(array[i]);
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • @orcmid:如果数组为空,那么仍然会给出正确的输出 - 空字符串.我不确定你的观点是什么. (5认同)

S.L*_*ott 6

显式循环总是比隐式循环更好.

builder.append( "" + array[0] );
for( int i = 1; i != array.length; i += 1 ) {
   builder.append( ", " + array[i] );
}
Run Code Online (Sandbox Code Playgroud)

你应该将整个事情包装在if语句中,以防你处理零长度数组.

  • 为什么每个人都继续使用字符串连接的示例INSIDE of append?","+ x编译成新的StringBuilder(",").append(x).toString()... (2认同)

Gar*_*vis 5

保持简单并使用标准for循环:

for(int i = 0 ; i < array.length ; i ++ ){
    builder.append(array[i]);
    if( i != array.length - 1 ){
        builder.append(',');
    }
}
Run Code Online (Sandbox Code Playgroud)

或者只使用apache commons-lang StringUtils.join()


小智 5

正如工具包提到的,在 Java 8 中我们现在有了Collectors。代码如下所示:

String joined = array.stream().map(Object::toString).collect(Collectors.joining(", "));
Run Code Online (Sandbox Code Playgroud)

我认为这正是您所寻找的,并且这是一种可以用于许多其他事情的模式。