Last iteration of enhanced for loop in java

JavaFor LoopForeachConditional Execution

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

Another alternative is to append the comma before you append i, just not on the first iteration. (Please don't use "" + i, by the way - you don't really want concatenation here, and StringBuilder has a perfectly good append(int) overload.)

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. (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.)

Solution 2 - Java

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

Solution 3 - Java

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

Solution 4 - Java

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

Solution 5 - Java

This is almost a repeat of this StackOverflow question. What you want is StringUtils, and to call the join method.

StringUtils.join(strArr, ',');

Solution 6 - Java

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

Solution 7 - Java

keep it simple and use a standard for loop:

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

Solution 8 - Java

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.

Solution 9 - Java

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.

Solution 10 - Java

As toolkit mentioned, in Java 8 we now have Collectors. 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.

Solution 11 - Java

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

Solution 12 - Java

You need Class Separator.

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

The implementation of class Separator is straight forward. It wraps a string that is returned on every call of toString() except for the first call, which returns an empty string.

Solution 13 - Java

Based on java.util.AbstractCollection.toString(), it exits early to avoid the delimiter.

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.

Solution 14 - Java

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

Solution 15 - Java

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.

Solution 16 - Java

Here's a SSCCE benchmark I ran (related to what I had to implement) with these results:

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

Solution 17 - Java

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.

Solution 18 - Java

Two alternate paths here:

1: Apache Commons String Utils

2: Keep a boolean called first, set to true. In each iteration, if first is false, append your comma; after that, set first to false.

Solution 19 - Java

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.

Solution 20 - Java

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

Solution 21 - Java

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.

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

Solution 22 - Java

You can use StringJoiner.

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

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

System.out.println(stringJoiner);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMercuriousView Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavatoolkitView Answer on Stackoverflow
Solution 3 - JavaDinahView Answer on Stackoverflow
Solution 4 - JavaOmar KoohejiView Answer on Stackoverflow
Solution 5 - JavaPhil HView Answer on Stackoverflow
Solution 6 - Javabruno condeView Answer on Stackoverflow
Solution 7 - JavaGareth DavisView Answer on Stackoverflow
Solution 8 - JavaS.LottView Answer on Stackoverflow
Solution 9 - JavasblundyView Answer on Stackoverflow
Solution 10 - Javab1tw153View Answer on Stackoverflow
Solution 11 - JavaFallenAvatarView Answer on Stackoverflow
Solution 12 - JavaakuhnView Answer on Stackoverflow
Solution 13 - Java13renView Answer on Stackoverflow
Solution 14 - JavaPeter LawreyView Answer on Stackoverflow
Solution 15 - JavaJulien ChastangView Answer on Stackoverflow
Solution 16 - JavaBuffaloView Answer on Stackoverflow
Solution 17 - JavaBrianView Answer on Stackoverflow
Solution 18 - JavaPaul BrinkleyView Answer on Stackoverflow
Solution 19 - JavaDinahView Answer on Stackoverflow
Solution 20 - JavafastcodejavaView Answer on Stackoverflow
Solution 21 - JavaAnthonyJClinkView Answer on Stackoverflow
Solution 22 - JavaHari KrishnaView Answer on Stackoverflow