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

147

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

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

for(int i : array)
{
    builder.append("" + i);
    if(!lastiteration)
        builder.append(",");
}

现在的问题是我不想在最后一次循环中添加逗号。现在是否有方法确定它是否为最后一次迭代,或者我只能使用for循环或外部计数器来跟踪。


3
是啊!真有趣,我也正想问同样的问题呢! - PhiLho
同样类型的问题会一再出现。那么,如果一个元素需要不同的处理,为什么要创建一个循环呢?https://dev59.com/AHVC5IYBdhLWcg3w4VVz - xtofl
既然你有一个固定的数组,为什么要使用增强型for循环?for(int i = 0; i< array.length; i++ if(i < array.lenth)... - AnthonyJClink
22个回答

225

另一种选择是在附加i之前附加逗号,只是不要在第一个迭代上这样做。(顺便说一下,请不要使用"" + i - 在这里您并不需要串联,而StringBuilder有一个非常好的append(int)重载函数。)

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

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

这个方法的好处是它适用于任何 Iterable - 您并不总能索引所有东西。(在您真的使用 StringBuilder 时,“添加逗号然后在最后删除它”是一个不错的建议,但对于像写入流这样的事情则行不通。不过,对于这个确切的问题,这可能是最好的方法。)


2
好的模式,但是builder.length() != 0很脆弱 - 想象一下在循环之前有条件地向缓冲区添加了某些内容。相反,使用一个“isFirst”布尔标志。奖励:速度更快。 - Jason Cohen
2
@Jason:我确实使用“isFirst”模式,在第一次迭代时生成器不会为空。但是,根据我的经验,当它不需要时,它会增加相当数量的代码膨胀。 - Jon Skeet
3
@利物浦(等): 进行1000次不必要的检查对性能几乎没有任何影响。我可能同样指出Dinah的解决方案添加的额外字符可能会导致StringBuilder需要扩展,将最终字符串的大小加倍(cont)。 - Jon Skeet
2
不必要的缓冲空间。然而,重要的是易读性。我认为我的版本比Dinah的更易读。如果你持有相反的观点,那也没关系。只有在找到瓶颈之后才考虑不必要的“ifs”对性能的影响。 - Jon Skeet
3
此外,我的解决方案更具普适性,因为它只依赖于能够写入。您可以采用我的解决方案,并更改以写入流等位置,在那里您可能无法取回不必要的数据。我喜欢通用的模式。 - Jon Skeet
显示剩余8条评论

148

另一种方法是:

String delim = "";
for (int i : ints) {
    sb.append(delim).append(i);
    delim = ",";
}

更新:对于Java 8,现在您可以使用Collectors


1
不得不删除我的类似答案 - 这会教训我在查看其他答案之前不要发布。 - Michael Burr
1
还要注意,这种技术处理了Robert Paulson在另一个评论线程中提到的潜在问题 - 这种技术不依赖于在附加数组值时StringBuilder为空。 - Michael Burr
1
尽管这个代码更加流畅/整洁/有趣,但是它不如if语句的版本容易理解。总是使用更加明显/可读的版本。 - Bill K
8
@Bill:这不是一个硬性规定,有时“聪明”的解决方案才是“更正确”的解决方案。更重要的是,你真的认为这个版本难以阅读吗?无论如何,维护者都需要逐步审查它——我认为这种差异并不重要。 - Greg Case
这样做是可以的,尽管你写入了其他资源,比如文件系统的写入调用。好主意。 - Tuxman

39

可能始终添加文本会更容易。然后,在循环结束时,只需删除最后一个字符即可。这种方法还可以减少大量条件判断。

您可以使用 StringBuilderdeleteCharAt(int index) 方法,其中索引为 length() - 1


5
这个问题最有效的解决方案。+1。 - Real Red.
10
也许这是我的问题,但我真的不喜欢你删除刚刚添加的内容... - Fortega
2
Fortega:我不喜欢每次都检查那99%的时间我会做的事情。应用Dinah或sblundy的方案似乎更合理(而且速度更快)。 - Buffalo
1
我认为这是最优雅的解决方案。谢谢! - Charles Morin

33

也许你正在使用错误的工具来完成任务。

虽然这种方法比你现在所做的更加手动,但它更加优雅,即使有点 "老派"。

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

16

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]);
        }
    }

这是一个自然的解决方案,只要数组不为空就可以实现。 - orcmid
5
如果数组为空,那么这个操作仍然会得到正确的输出——一个空字符串。我不确定你的意思是什么。 - Eddie

7

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

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

或者只需使用Apache的commons-lang StringUtils.join()

。该函数可以将一个对象数组连接为一个字符串,并且可以指定分隔符。


6

明确的循环比隐式的循环效果更好。

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

为了防止处理长度为零的数组,应该将整个内容包装在if语句中。


我喜欢这种方法,因为它不会在每次迭代中无谓地执行测试。唯一需要补充的是,构建器可以直接附加整数,因此无需使用"" + int,只需附加(array [0])。 - Josh
你需要再加一个if语句来保证数组至少有一个元素。 - Tom Leys
2
为什么每个人都要在 append 中使用字符串拼接的示例? ", " + x 编译成新的 StringBuilder (", ").append( x ).toString() ... - John Gardner
@Josh 和 @John:只是跟随 n00b 的例子。不想一次引入太多东西。然而,你们的观点非常好。 - S.Lott
@Tom:没错,我想我已经说过了。不需要编辑。 - S.Lott

5

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

String joined = array.stream().map(Object::toString).collect(Collectors.joining(", "));

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

4
如果你将它转换成经典的索引循环,是可以的。
或者你也可以在完成后删除最后一个逗号。就像这样:
int[] array = {1, 2, 3...};
StringBuilder

builder = new StringBuilder();

for(int i : array)
{
    builder.append(i + ",");
}

if(builder.charAt((builder.length() - 1) == ','))
    builder.deleteCharAt(builder.length() - 1);

对于我来说,我只是使用StringUtils.join()函数,它来自于commons-lang库。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接