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

有没有办法确定循环是否在最后一次迭代。我的代码是这样的:

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


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

现在的问题是,我不想在上一次迭代中添加逗号。现在有没有一种方法可以确定这是最后一次迭代,或者我被 for 循环卡住了,或者使用外部计数器来跟踪。

82614 次浏览

也许总是附加会更容易些。然后,当您完成循环时,只需删除最后一个字符。这样条件句也少了很多。

可以使用 StringBuilderdeleteCharAt(int index),索引为 length() - 1

如果你把它转换成一个经典的索引循环,是的。

或者你可以在完成后删除最后一个逗号,像这样:

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

我只用 Commons-langStringUtils.join()

保持简单并使用标准的 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 ()

显式循环总是比隐式循环工作得更好。

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

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

另一种方法是在添加 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);
}

这样做的好处是,它可以与任何 Iterable一起工作-你不能总是索引东西。(当你真正使用 StringBuilder 时,“添加逗号,然后在末尾删除它”是一个很好的建议——但是它不适用于像写入流这样的事情。不过,这可能是解决这个问题的最佳方法。)

另一种方法是将数组的长度(如果可用)存储在一个单独的变量中(比每次重新检查长度更有效)。然后可以将索引与该长度进行比较,以确定是否添加最后一个逗号。

编辑: 另一个考虑因素是权衡删除最终字符(可能导致字符串副本)和在每次迭代中检查条件的性能成本。

这里有一个解决方案:

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


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


builder.append("" + i);
firstiteration=false;
}

寻找第一个迭代:)

这里有两条可供选择的路径:

1: Apache Commons String Utils

2: 保持一个名为 first的布尔值,设置为 true。在每次迭代中,如果 first为 false,则添加逗号; 在此之后,将 first设置为 false。

也许你在工作中使用了错误的工具。

这是更多的手动比你正在做什么,但它在某种程度上更优雅,如果不是有点“老学校”

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

另一个解决方案(也许是最有效的)

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

另一种方法是:

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

更新: 对于 Java8,现在有了 收藏家

如果只是将数组转换为逗号分隔的数组,那么许多语言都有一个联接函数来实现这一点。它将数组转换为每个元素之间有分隔符的字符串。

你需要 分类器

Separator s = new Separator(", ");
for(int i : array)
{
builder.append(s).append(i);
}

Separator的实现非常简单。它包装一个字符串,该字符串在 toString()的每次调用中返回,但第一次调用除外,该调用返回一个空字符串。

基于 java.util.AbstractCollection.toString () ,它提前退出以避免使用分隔符。

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

它高效而优雅,但不像其他一些答案那样不言自明。

还有一个选择。

StringBuilder builder = new StringBuilder();
for(int i : array)
builder.append(',').append(i);
String text = builder.toString();
if (text.startsWith(",")) text=text.substring(1);

这几乎是 这个 StackOverflow 问题的重复。你需要的是 StringUtils,并调用 加入方法。

StringUtils.join(strArr, ',');

恕我直言,这里描述的许多解决方案都有点过头,尤其是那些依赖于外部库的解决方案。有一个很好的干净,清晰的习惯用法实现逗号分隔的列表,我一直使用。它依赖于条件(?)接线员:

编辑 : 原始解决方案正确,但根据评论不是最佳。再试一次:

    int[] array = {1, 2, 3};
StringBuilder builder = new StringBuilder();
for (int i = 0 ;  i < array.length; i++)
builder.append(i == 0 ? "" : ",").append(array[i]);

好了,这4行代码包括数组和 StringBuilder 的声明。

在这种情况下,真的没有必要知道这是否是最后一次重复。 我们有很多方法可以解决这个问题,一个方法是:

String del = null;
for(int i : array)
{
if (del != null)
builder.append(del);
else
del = ",";
builder.append(i);
}

下面是我运行的 SSCCE 基准测试(与我必须实现的内容相关) ,其结果如下:

elapsed time with checks at every iteration: 12055(ms)
elapsed time with deletion at the end: 11977(ms)

至少在我的示例中,在每次迭代中跳过检查并不明显地更快,特别是对于正常数据量而言,但 更快。

import java.util.ArrayList;
import java.util.List;




public class TestCommas {


public static String GetUrlsIn(int aProjectID, List<String> aUrls, boolean aPreferChecks)
{


if (aPreferChecks) {


StringBuffer sql = new StringBuffer("select * from mytable_" + aProjectID + " WHERE hash IN ");


StringBuffer inHashes = new StringBuffer("(");
StringBuffer inURLs = new StringBuffer("(");


if (aUrls.size() > 0)
{


for (String url : aUrls)
{


if (inHashes.length() > 0) {
inHashes.append(",");
inURLs.append(",");
}


inHashes.append(url.hashCode());


inURLs.append("\"").append(url.replace("\"", "\\\"")).append("\"");//.append(",");


}


}


inHashes.append(")");
inURLs.append(")");


return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString();
}


else {


StringBuffer sql = new StringBuffer("select * from mytable" + aProjectID + " WHERE hash IN ");


StringBuffer inHashes = new StringBuffer("(");
StringBuffer inURLs = new StringBuffer("(");


if (aUrls.size() > 0)
{


for (String url : aUrls)
{
inHashes.append(url.hashCode()).append(",");


inURLs.append("\"").append(url.replace("\"", "\\\"")).append("\"").append(",");
}


}


inHashes.deleteCharAt(inHashes.length()-1);
inURLs.deleteCharAt(inURLs.length()-1);


inHashes.append(")");
inURLs.append(")");


return sql.append(inHashes).append(" AND url IN ").append(inURLs).toString();
}


}


public static void main(String[] args) {
List<String> urls = new ArrayList<String>();


for (int i = 0; i < 10000; i++) {
urls.add("http://www.google.com/" + System.currentTimeMillis());
urls.add("http://www.yahoo.com/" + System.currentTimeMillis());
urls.add("http://www.bing.com/" + System.currentTimeMillis());
}




long startTime = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
GetUrlsIn(5, urls, true);
}
long endTime = System.currentTimeMillis();
System.out.println("elapsed time with checks at every iteration: " + (endTime-startTime) + "(ms)");


startTime = System.currentTimeMillis();
for (int i = 0; i < 300; i++) {
GetUrlsIn(5, urls, false);
}
endTime = System.currentTimeMillis();
System.out.println("elapsed time with deletion at the end: " + (endTime-startTime) + "(ms)");
}
}

正如工具包提到的,在 Java8中我们现在有了 收藏家:

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

我觉得这正是你想要的,这种模式你可以用在很多其他事情上。

因为它是一个固定的数组,所以更容易简单地避免增强的 for... 如果 Object 是一个集合,迭代器会更容易。

int nums[] = getNumbersArray();
StringBuilder builder = new StringBuilder();


// non enhanced version
for(int i = 0; i < nums.length; i++){
builder.append(nums[i]);
if(i < nums.length - 1){
builder.append(",");
}
}


//using iterator
Iterator<int> numIter = Arrays.asList(nums).iterator();


while(numIter.hasNext()){
int num = numIter.next();
builder.append(num);
if(numIter.hasNext()){
builder.append(",");
}
}

你可以使用 StringJoiner

int[] array = { 1, 2, 3 };
StringJoiner stringJoiner = new StringJoiner(",");


for (int i : array) {
stringJoiner.add(String.valueOf(i));
}


System.out.println(stringJoiner);