Что является более эффективным StringBuffer new () или delete (0, sb.length ())? - PullRequest
14 голосов
/ 24 августа 2011

Часто утверждают, что избегание создания объектов (особенно в циклах) считается хорошей практикой.

Тогда, что наиболее эффективно в отношении StringBuffer?

StringBuffer sb = new StringBuffer();
ObjectInputStream ois = ...;

for (int i=0;i<1000;i++) {

    for (j=0;i<10;j++) {
        sb.append(ois.readUTF());
    }
    ...

    // Which option is the most efficient? 
    sb = new StringBuffer(); // new StringBuffer instance?
    sb.delete(0,sb.length()); // or deleting content?

}

Я имею в виду, можно утверждать, что создание объекта происходит быстрее, чем цикл по массиву.

Ответы [ 3 ]

16 голосов
/ 24 августа 2011

First StringBuffer является потокобезопасным, что будет иметь плохую производительность по сравнению с StringBuilder. StringBuilder не является потокобезопасным, но в результате быстрее. Наконец, я предпочитаю просто установить длину в 0, используя setLength .

sb.setLength(0)

Это похоже на .delete(...), за исключением того, что вам не важна длина. Также, вероятно, немного быстрее, так как не нужно ничего ' удалять '. Создание нового StringBuilder (или StringBuffer) будет менее эффективным. Каждый раз, когда вы видите new, Java создает новый объект и помещает его в кучу.

Примечание : После рассмотрения реализации .delete и .setLength, .delete устанавливает длину = 0, а .setLength устанавливает каждую вещь на '\0' Так что вы можете получить немного выиграть с .delete

3 голосов
/ 06 июля 2012

Просто для усиления предыдущих комментариев:

При просмотре источника delete () всегда вызывает System.arraycopy (), но если аргументы (0, количество), он будет вызывать arraycopy () с нулевой длиной, которая, вероятно, не будет иметь никакого эффекта.ИМХО, это должно быть оптимизировано, так как я держу пари, что это самый распространенный случай, но неважно.

С setLength (), с другой стороны, вызов увеличит емкость StringBuilder, если это необходимо, посредством вызовав ensureCapacityInternal () (еще один очень распространенный случай, который должен был быть оптимизирован из IMHO), а затем усекает длину, как delete ().

В конечном итоге оба метода просто заканчивают настройку count до нуля.

Ни один из вызовов не выполняет итерации в этом случае.Оба делают ненужный вызов функции.Однако sureCapacityInternal () - это очень простой закрытый метод, который предлагает компилятору почти полностью оптимизировать его, поэтому вполне вероятно, что setLength () немного более эффективен.

Я крайне скептически отношусь к созданиюНовый экземпляр StringBuilder может быть настолько же эффективным, как просто установка count на ноль, но я полагаю, что компилятор может распознать задействованный шаблон и преобразовать повторяющиеся экземпляры в повторяющиеся вызовы в setLength (0),Но в лучшем случае это будет стирка.И вы зависите от компилятора, который распознает регистр.

Резюме: setLength (0) является наиболее эффективным.Для максимальной эффективности предварительно выделите буферное пространство в StringBuilder при его создании.

1 голос
/ 24 августа 2011

Метод удаления реализован следующим образом:

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

Как видите, он не перебирает массив.

...