DeleteCharAt или setLength, в каком пути лучше удалить последний char из StringBuilder/StringBuffer

Во многих случаях нам нужно удалить последний char StringBuilder/StringBuffer. Например, с учетом int[]{1,2,3}, реализовать метод String toString(int[] a), связав каждый элемент с разделителем запятой. Выход должен быть 1,2,3, без хвостовой запятой.

Мы можем легко написать цикл:

int[] nums = new int[]{1,2,3,4,5};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < nums.length; i++) {
    sb.append(nums[i]);
    sb.append(",");
}
//here we need to remove the tailing ','

но всегда нужно удалить хвостовик ','. Существует два способа его реализации:

sb.deleteCharAt(sb.length() - 1);

и

sb.setLength(sb.length() - 1);

Какой из них рекомендуется? Почему?

Примечание: Я знаю, что делает Arrays.toString. Это просто пример, чтобы описать мой вопрос, может быть, не совсем правильно. Это не обсуждение конкатенации строк, а лучшие практики StringBuffer/StringBuilder.

Ответ 1

На самом деле, в нем очень мало и, вероятно, зависит от оборудования и других факторов.

Метод setLength() просто изменяет счетчик и перезаписывает ненужное значение в массиве с нулевым байтом.

deleteCharAt() выполняет внутреннюю копию массива, прежде чем изменять счетчик. Это звучит драматично, но копируемый массив фактически нулевой длины, потому что вы удаляете последний символ.

Я бы порекомендовал идти за setLength(), поскольку он короче набирать, и я думаю, что он ясно показывает, что вы делаете. Если производительность является проблемой, и при измерении вы обнаружите, что это узкое место для вас, то, возможно, вы могли бы рассмотреть другой алгоритм, который не требует изменения размера (согласно ответам JB Nizet).

Ответ 2

Как вы это делаете, это условно добавить запятую:

for (int i = 0; i < nums.length; i++) {
    if (i > 0)
        sb.append(',');
    sb.append(nums[i]);
}

Тогда вам не нужно беспокоиться об удалении последнего символа, потому что он уже прав.

Ответ 3

Я бы так не сделал. Вместо этого я бы добавил только конечную запятую, если элемент не является последним элементом массива. Или я бы использовал Guava Joiner (или Apache-commons StringUtils), что делает его более ясным:

String s = Joiner.on(',').join(nums);

NB: Я только заметил, что Guava Joiner не имеет дело с примитивными массивами. Вы все равно должны получить эту идею.