简体   繁体   English

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

[英]Last iteration of enhanced for loop in java

Is there a way to determine if the loop is iterating for the last time.有没有办法确定循环是否是最后一次迭代。 My code looks something like this:我的代码看起来像这样:

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

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

Now the thing is I don't want to append the comma in the last iteration.现在的问题是我不想在最后一次迭代中附加逗号。 Now is there a way to determine if it is the last iteration or am I stuck with the for loop or using an external counter to keep track.现在有没有办法确定它是最后一次迭代还是我坚持使用 for 循环或使用外部计数器来跟踪。

Another alternative is to append the comma before you append i, just not on the first iteration. 另一种方法是在追加i之前附加逗号,而不是在第一次迭代时。 (Please don't use "" + i , by the way - you don't really want concatenation here, and StringBuilder has a perfectly good append(int) overload.) (请不要使用"" + 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);
}

The nice thing about this is that it will work with any Iterable - you can't always index things. 关于这个的Iterable是它可以与任何Iterable - 你不能总是索引事物。 (The "add the comma and then remove it at the end" is a nice suggestion when you're really using StringBuilder - but it doesn't work for things like writing to streams. It's possibly the best approach for this exact problem though.) (当你真正使用StringBuilder时,“添加逗号然后将其删除”是一个很好的建议 - 但它不适用于写入流等内容。虽然这可能是解决这个问题的最佳方法。 )

Another way to do this: 另一种方法:

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

Update: For Java 8, you now have Collectors 更新:对于Java 8,您现在拥有收集器

It might be easier to always append. 总是追加可能更容易。 And then, when you're done with your loop, just remove the final character. 然后,当你完成循环时,只需删除最后一个字符。 Tons less conditionals that way too. 通过这种方式减少条件。

You can use StringBuilder 's deleteCharAt(int index) with index being length() - 1 您可以使用StringBuilderdeleteCharAt(int index) ,索引为length() - 1

Maybe you are using the wrong tool for the Job. 也许你正在使用错误的工具来完成工作。

This is more manual than what you are doing but it's in a way more elegant if not a bit "old school" 这比你正在做的更加手动,但如果不是有点“老派”,它会更优雅

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

This is almost a repeat of this StackOverflow question . 这几乎是StackOverflow问题的重复。 What you want is StringUtils , and to call the join method. 你想要的是StringUtils ,并调用join方法。

StringUtils.join(strArr, ',');

Another solution (perhaps the most efficient) 另一种解决方案(也许效率最高)

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

Explicit loops always work better than implicit ones. 显式循环总是比隐式循环更好。

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

You should wrap the whole thing in an if-statement just in case you're dealing with a zero-length array. 你应该将整个事情包装在if语句中,以防你处理零长度数组。

keep it simple and use a standard for loop: 保持简单并使用标准for循环:

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

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

If you convert it to a classic index loop, yes. 如果将其转换为经典索引循环,是的。

Or you could just delete the last comma after it's done. 或者你可以在完成后删除最后一个逗号。 Like so: 像这样:

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

Me, I just use StringUtils.join() from commons-lang . 我,我只是使用commons-lang的 StringUtils.join()

You need Class Separator . 你需要Class Separator

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

The implementation of class Separator is straight forward. Separator的实现很简单。 It wraps a string that is returned on every call of toString() except for the first call, which returns an empty string. 它包装了每次调用toString()返回的字符串,除了第一次调用,它返回一个空字符串。

Based on java.util.AbstractCollection.toString(), it exits early to avoid the delimiter. 基于java.util.AbstractCollection.toString(),它会提前退出以避免分隔符。

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

It's efficient and elegant, but not as self-evident as some of the other answers. 它既高效又优雅,但不像其他一些答案那样不言自明。

Here is a solution: 这是一个解决方案:

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

Look for the first iteration :) 寻找第一次迭代:)

Here's a SSCCE benchmark I ran (related to what I had to implement) with these results: 这是我运行的SSCCE基准测试(与我必须实现的相关)以及这些结果:

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

On my example at least, skipping the check at every iteration isn't noticeably faster especially for sane volumes of data, but it is faster. 至少在我的例子,在每次迭代跳过检查并无明显改善尤其是对数据的健全卷,但它速度更快。

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

As toolkit mentioned, in Java 8 we now have Collectors . 正如工具包所提到的,在Java 8中我们现在有了收集器 Here's what the code would look like: 这是代码的样子:

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

I think that does exactly what you're looking for, and it's a pattern you could use for many other things. 我认为这正是你正在寻找的东西,而且这是你可以用于许多其他事情的模式。

Yet another option. 还有另一种选择。

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

Many of the solutions described here are a bit over the top, IMHO, especially those that rely on external libraries. 这里描述的许多解决方案都有点过头了,恕我直言,特别是那些依赖外部库的解决方案。 There is a nice clean, clear idiom for achieving a comma separated list that I have always used. 有一个很好的干净,清晰的习惯用法来实现我一直使用的逗号分隔列表。 It relies on the conditional (?) operator: 它依赖于条件(?)运算符:

Edit : Original solution correct, but non-optimal according to comments. 编辑 :原始解决方案正确,但根据评论非最佳。 Trying a second time: 第二次尝试:

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

There you go, in 4 lines of code including the declaration of the array and the StringBuilder. 你可以在4行代码中找到,包括数组的声明和StringBuilder。

Another approach is to have the length of the array (if available) stored in a separate variable (more efficient than re-checking the length each time). 另一种方法是将数组的长度(如果可用)存储在单独的变量中(比每次重新检查长度更有效)。 You can then compare your index to that length to determine whether or not to add the final comma. 然后,您可以将索引与该长度进行比较,以确定是否添加最终逗号。

EDIT: Another consideration is weighing the performance cost of removing a final character (which may cause a string copy) against having a conditional be checked in each iteration. 编辑:另一个考虑因素是权衡去除最终字符(可能导致字符串副本)的性能成本,而不是在每次迭代中检查条件。

Two alternate paths here: 这里有两条备用路径:

1: Apache Commons String Utils 1: Apache Commons String Utils

2: Keep a boolean called first , set to true. 2:保持一个名为first的布尔值,设置为true。 In each iteration, if first is false, append your comma; 在每次迭代中,如果first为false,则附加逗号; after that, set first to false. 之后, first设置为false。

If you're only turning an array into a comma delimited array, many languages have a join function for exactly this. 如果您只是将数组转换为逗号分隔数组,则许多语言都具有连接函数。 It turns an array into a string with a delimiter between each element. 它将数组转换为一个字符串,每个元素之间都有一个分隔符。

Since its a fixed array, it would be easier simply to avoid the enhanced for... If the Object is a collection an iterator would be easier. 由于它是一个固定的数组,因此简单地避免增强...更容易。如果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(",");
   }
}

In this case there is really no need to know if it is the last repetition. 在这种情况下,实际上不需要知道它是否是最后一次重复。 There are many ways we can solve this. 我们有很多方法可以解决这个问题。 One way would be: 一种方法是:

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

You can use StringJoiner .您可以使用StringJoiner

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

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

System.out.println(stringJoiner);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM