Have you ever wrote code similar with?:

boolean first = true;
StringBuilder result = new StringBuilder("");
 
for (Item item : collection) {
  if (!first) {
    result.append(", ");
  } else {
      first = false;
  }
 
  result.append(item);
}

I did, and I more often than not need this kind of code, and, as you do, I also dislike it.

It's ugly, hard to figure out what it does unless you stop a bit to think. This is why on my Germanium project I've picked a different strategy. I've created a class named OnceFirstIterator that contains the full "if first item state in it".

So no more if (first) then blah.

How does the end code look? I believe it's awesome, but you be the judge:

Simple list joining

OnceFirstIterator<String> comma = new OnceFirstIterator<String>("", ", ");
StringBuilder result = new StringBuilder("");
 
for (Item item : collection) {
  result.append(comma.next())
    .append(item);
}

or

Query path processing

OnceFirstIterator<String> parameterJoiner = new OnceFirstIterator<String>("?", "&amp;");
StringBuilder queryPath = new StringBuilder("");
 
for (Item queryItem : queryParameters) {
  result.append(parameterJoiner.next())
    .append(queryItem);
}

or

Basic SQL building

OnceFirstIterator<String> whereKeyword = new OnceFirstIterator<String>(" where ", " and ");
OnceFirstIterator<String> orderByKeyword = new OnceFirstIterator<String>(" order by ", ", ");
StringBuilder sql = new StringBuilder(...);
 
for (WhereClause whereClause : whereClauses) {
  sql.append(whereKeyword.next())
    .append(whereClause);
}
for (OrderByClause orderByClause : orderByClauses) {
  sql.append(orderByKeyword.next())
    .append(orderByClause);
}

So what are you waiting? Here is also a JavaScript implementation:

var onceMany = function(once, many) {
    var firstGenerated = false;
    return {
        next : function() {
            if (firstGenerated) {
                return many;
            } else {
                firstGenerated = true;
                return once;
            }
        }
    }
};

and some small JSON encoding using it:

    result = "{ ";
    var comma = onceMany("", ", ");
    for (var key in object) {
        result += comma.next() + "'" + key.replace(/'/g, "\\'") + "' : " +  jsonStringify(object[key]);
    }
    result += "}";
 

Germanium

The one to rule them all. The browsers that is.

SharpKnight

SharpKnight is an Android chess game.

MagicGroup

MagicGroup is an eclipse plugin.

Go to top