Подтвердить что ты не робот

StringBuilder - Reset или создать новый

У меня есть условие, что StringBuilder сохраняет строки, соответствующие шаблону, из большого плоского файла (100 МБ). Однако после достижения условия я пишу содержимое varialble StringBuilder в текстовый файл.

Теперь я задаюсь вопросом, следует ли использовать ту же переменную, сбросив объект →

stringBuilder.delete(0,stringBuilder.length())

ИЛИ

stringBuilder=new StringBuilder();

Просьба предложить, какой из них, по вашему мнению, лучше, насколько это касается проблем производительности и OOM.

4b9b3361

Ответ 1

Я думаю, что StringBuilder#delete(start, end) по-прежнему дорогой звонок, вы должны сделать:

stringBuilder.setLength(0);

до reset it.


ОБНОВЛЕНИЕ: После просмотра исходного кода StringBuilder Кажется, t23 > оставляет старый буфер неповрежденным, и лучше вызвать: StringBuilder#trimToSize() после вызова выше attempts to reduce storage used for the character sequence.

Итак, что-то вроде этого было бы более эффективным:

stringBuilder.setLength(0); // set length of buffer to 0
stringBuilder.trimToSize(); // trim the underlying buffer

Ответ 2

Imho, я бы предложил использовать новое:

stringBuilder = new StringBuilder();

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

В худшем случае, возможно, вы потеряете некоторую эффективность, и gc получает тренировку, но вы исключаете возможность OOM.

Из-за этого, а также по соображениям я бы лично принял новый подход.

Ответ 3

Одно фундаментальное различие заключается в том, что sb.delete сохраняет ссылку, а конструктор теряет ее.

Если ваш SB является аргументом метода и должен использоваться для передачи контента обратно вызывающему, вы должны использовать sb.delete. Вызывающий имеет исходную ссылку.

Ответ 4

Ну, там большая разница между ними. Первый сохраняет все возможности, которые он имел до того, как вы удалили символы (т.е. stringBuilder.capacity()), тогда как второй создает новый StringBuilder с мощностью по умолчанию 16. Конечно, вы можете просто передать stringBuilder.capacity() в качестве аргумента конструктору, но, тем не менее, важно понимать различие здесь.

В любом случае, я очень сомневаюсь, что вы увидите существенную разницу в производительности между этими двумя вариантами, поэтому выберите то, что более читаемо и проще в управлении. Только когда вы окончательно определили, что это вызывает какое-то узкое место, если вы измените свой подход.

Ответ 5

Я бы использовал:

 stringBuilder = new StringBuilder();

потому что, если вы заполняете его большим количеством данных, вызов stringBuilder.setLength(0); не освободит массив подстановки, поэтому вы можете видеть, что использование памяти остается неоправданным.

Кроме того, это проще читать и понимать.

Ответ 6

В идеале мы должны использовать new StringBuilder() Копаем немного в классе StringBuilder из grepcode Я узнаю следующее.

Создание нового объекта:

/**
     * Creates an AbstractStringBuilder of the specified capacity.
     */
    AbstractStringBuilder(int capacity) {
        value = new char[capacity];
    }

new StringBuilder() создает новый объект с начальным размером массива char. Накладные расходы здесь: GC будет вызван для очистки старого объекта.

Использование delete:

public AbstractStringBuilder delete(int start, int end) {
        if (start < 0)
            throw new StringIndexOutOfBoundsException(start);
        if (end > count)
            end = count;
        if (start > end)
            throw new StringIndexOutOfBoundsException();
        int len = end - start;
        if (len > 0) {
            System.arraycopy(value, start+len, value, start, count-end);
            count -= len;
        }
        return this;
    }

Использование Length и TrimToSize:

public void trimToSize() {
        if (count < value.length) {
            value = Arrays.copyOf(value, count);
        }
    }

Вызов copyOf из класса массива

public static char [] copyOf (char [] original, int newLength) {   char [] copy = new char [newLength];   System.arraycopy(оригинал, 0, копия, 0,                    Math.min(original.length, newLength));   возвратная копия; }

Теперь он также вызовет System.arrayCopy, который является родным методом. Теперь, если вы видите в copyOf, мы создаем новый charArray снова длиной 0, и когда мы попытаемся добавить к нему лишние данные, он будет вызывать расширение, потому что текущая длина будет 0. Поэтому я думаю, что лучше назвать новый StringBuilder()

Вы можете увидеть приведенный выше код на grepcode

PS: @user3241961 записывается в том случае, если вы используете ссылку на этот объект, а затем новый должен будет снова установить его

Ответ 7

Если вы находитесь в жестком цикле, и вы продолжите работу в этом цикле после того, как вы напишете данные в файл, вы должны обязательно повторно использовать StringBuilder. Там нет причин не делать этого, и это лучше, чем взбалтывать GC. Если вы пишете это на C или С++, вы повторно используете буфер.

Кроме того, хотя true, что метод delete (...) вызывает System.arraycopy, количество копируемых байтов равно 0, поэтому оно незначительно.

Ah - кто-то еще сказал мне, что существует метод setLength (...), который является самым быстрым способом повторного использования буфера.

Ответ 8

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

Более быстрый способ:

stringBuilder.setLength(0);