Несколько StringBuilder внутри StringBuilder. Это стоит? - PullRequest
1 голос
/ 08 ноября 2019

Я получаю список моделей. Количество моделей может быть большим. Эта модель имеет множество свойств, и любое из них может быть null потенциально.

Мне нужно построить строку для каждой модели на основе ее свойств. Если property == null , тогда я добавляю некоторую статическую часть к результирующей строке, например "property1 is null" .

If else property! = Null затем я добавляю что-то вроде этого "property1 == 'valueOfThePropertyHere'" .

Строка результата должна выглядеть примерно так: prop1 == 'value1' and prop2 is null and prop3 == 'value3' and prop4 == 'value4' and prop5 is null and ..... propN == 'valueN'

И я генерируютакая строка для каждой модели из списка.

Очевидно, я делаю это в цикле for и использую для этого StringBuilder. Дело в том, что в добавлении метода StringBuilder я проверяю все поля модели на нулевое значение с помощью тернарного оператора и на основании этого добавляю результат этой проверки в строку результата. Но если свойство не равно нулю, мне нужно добавить некоторую статическую часть + значение самого поля + еще несколько статических вещей. А это значит, что мне нужно добавить еще один StringBuilder для каждого свойства, которое у меня есть. Или я могу использовать «+», который в любом случае будет преобразован в StringBuilder, и насколько я знаю, это плохая практика - использовать «+» внутри StringBuilder (но я все равно должен его использовать).

Пример:

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

На мой взгляд, с точки зрения производительности это выглядит не очень хорошо, потому что для каждой модели из списка моделей я создаю еще одну группу объектов StringBuilder в куче, чтобы получить строку результата.

Я что-то упустил? Есть ли лучшие способы сделать это с точки зрения производительности? Или все нормально, потому что других вариантов пока не вижу.

Ответы [ 2 ]

5 голосов
/ 08 ноября 2019

Для простых.

Вместо

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

используйте:

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

Помимо явной странности использования StringBuilder внутри StringBuilder.append call (и почему бы просто не использовать + в любом случае ...), действительно трудно разобрать, где находится : в условном выражении. Разбить его на строки гораздо проще.


Если вам часто приходится повторять этот шаблон кода, определите метод:

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

и затем вызовите как:

append(stringBuilder, "field1", m.getField1());
append(stringBuilder, "field2", m.getField2());
append(stringBuilder, "field3", m.getField3());
0 голосов
/ 08 ноября 2019

Какой беспорядок! То, что вы можете вызывать цепочку, не означает, что вы должны:

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

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

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

        if(stringBuilder.length()>0) {
            stringBuilder.append(" and ");
        }

        field = m.getField2();
        if(field==null) {
            stringBuilder.append("field2 is null");
        } else {
            stringBuilder.append("field2 == ").append(m.getField1()).append("'");
        }

        if(stringBuilder.length()>0) {
            stringBuilder.append(" and ");
        }
        ...

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

Чтобы избежать всего этого потенциального повторения (в зависимости от количества полей):

void appendField(StringBuilder stringBuilder, String fieldName, String value) {
    if(stringBuilder.length()>0) {
        stringBuilder.append(" and ");
    }
    stringBuilder.append(fieldName);
    if(value==null) {
        stringBuilder.append(" is null");
    } else {
        stringBuilder.append(" == '").append(value).append("'");
    }
}
String toString(Model m) {
    StringBuilder stringBuilder = new StringBuilder();

    appendField(stringBuilder, "field1", m.getField1());
    appendField(stringBuilder, "field2", m.getField2());
    ...
    appendField(stringBuilder, "fieldN", m.getFieldN());

    return stringBuilder.toString();
}

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

for (Model m: models) {
    System.out.println(toString(m));
}
...