Multiple StringBuilders inside StringBuilder. Does it worth?

Coffemanz :

I receive a list of models. The number of models could be large. This models has a bunch of properties and any of them could be null potentially.

I need to build a string for every model based of it's properties. If property == null then I add some static part to the result string like "property1 is null".

If else property != null then I add something like this "property1 == 'valueOfThePropertyHere'".

The result string should look something like this: prop1 == 'value1' and prop2 is null and prop3 == 'value3' and prop4 == 'value4' and prop5 is null and ..... propN == 'valueN'

And I generate such string for every model from the list.

Obviously I do this in for loop and I use StringBuilder for this. The thing is that in append method of StringBuilder I check every field of the model for null using ternary operator and based on this I add the result of this check to the result string. But if a property is not null then I need to add some static part + value of the field itself + some more static stuff. And that means I need to add one more StringBuilder for every property I have. Or I can use '+' which will be transformed into StringBuilder anyway and as far as I know it's a bad practise to use '+' inside StringBuilder (but I have to use it anyway).

Example:

List<Model> models = repository.getModels();

for (Model m: models) {
    StringBuilder stringBuilder = new StringBuilder();

    stringBuilder
    .append(m.getField1() == null ? "field1  is null" : "field1 == '" + new StringBuiler().append(m.getField1()).append("'").append(" and ").toString()))
    .append(m.getField2() == null ? "field2  is null" : "field2 == '" + new StringBuiler().append(m.getField2()).append("'").append(" and ").toString()))
    ...............
    .append(m.getFieldN() == null ? "fieldN  is null" : "fieldN == '" + new StringBuiler().append(m.getFieldN()).append("'").append(" and ").toString()));

    System.out.println(stringBuilder.toString());
    }

In my opinion from the performance perspective it doesn't look so well because for every model from a list of models I create another bunch of StringBuilder objects in heap just to get the result string.

Am I missing something? Are there better ways to do so from the performance perspective? Or it's okay because I don't see other options for now.

Andy Turner :

Go for simple.

Instead of

stringBuilder
.append(m.getField1() == null ? "field1  is null" : "field1 == '" + new StringBuiler().append(m.getField1()).append("'").append(" and ").toString()))

use:

if (m.getField1() == null) {
  stringBuilder.append("field1  is null");
} else {
  stringBuilder.append("field1 == '").append(m.getField1()).append("'").append(" and ");
}

Aside from the distinct oddness of using a StringBuilder inside a StringBuilder.append call (and why not just use + anyway...), it's really hard to parse where the : is in the conditional expression. Breaking it into lines is much easier.


If you find yourself having to repeat this code pattern a lot, define a method:

void append(StringBuilder stringBuilder, String name, Object value) {
  stringBuilder.append(name);
  if (value == null) {
    stringBuilder.append(" is null");
  } else {
    stringBuilder.append(" == '").append(value).append("'").append(" and ");
  }
}

and then invoke like:

append(stringBuilder, "field1", m.getField1());
append(stringBuilder, "field2", m.getField2());
append(stringBuilder, "field3", m.getField3());

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=329696&siteId=1