Запуск pmd в коде с помощью StringBuilder дает ошибку об инициализированном размере и добавленном размере

private static String buildSomeString(Map<String, String> data) {
    StringBuilder result = new StringBuilder();
    for (Map.Entry<String, String> field : data.entrySet()) {
       result.append("some literal")
            .append(field.getKey())
            .append("another literal")
            .append(field.getKey())
            .append("and another one")
            .append(field.getValue())
            .append("and the last in this iteration");
     }
     return result.toString();
}

Когда я бегу pmd на этом я получаю следующую ошибку

StringBuffer constructor is initialized with size 16, but has at least 83 characters appended.

Количество символов, вероятно, неверно, потому что я изменил литералы перед публикацией.

Спасибо

2 ответа

Решение

StringBuilderКонструктор может дополнительно получить int с размером используемого внутреннего буфера. Если ничего не указано (как в вашем коде), по умолчанию используется значение 16.

Как вы добавляете данные на StringBuilder, он автоматически изменит размер внутреннего буфера по мере необходимости. Это изменение размера подразумевает создание нового, большего массива и копирование в него старых данных. Это "дорогостоящая" операция (обратите внимание на кавычки, это микрооптимизация, если вы используете плохие алгоритмы, такие как пузырьковая сортировка, у вас большие проблемы).

Делая более обоснованное предположение об ожидаемом размере строки, можно избежать / минимизировать такое перераспределение.

PMD не знает, что такое содержимое карты, но знает, что оно будет содержать не менее 83 символов (учитывая, что карта не пустая).

Это можно решить, сделав более обоснованное предположение о размере, например:

StringBuilder result = new StringBuilder(83 * data.size()); // 83 or whatever you constant strings account for

Это может быть уточнено, если вы сможете лучше приблизиться к ожидаемому значению ключей и значений карты. Обычно лучше немного перейти к фактическому ожидаемому результату, так как даже если он предполагает выделение большего объема памяти, у него больше шансов полностью избежать перераспределений.

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

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

Другие вопросы по тегам