Кэшируется ли метод ArrayList.size ()? - PullRequest
17 голосов
/ 18 мая 2010

Мне было интересно, является ли size() метод, который вы можете вызвать на существующем ArrayList<T>, кэшированным? Или в коде, критичном к производительности, предпочтительнее хранить size() в локальном int?

Я ожидаю, что он действительно кешируется, когда вы не добавляете / удаляете элементы между вызовами size().

Я прав?

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

Ответы [ 7 ]

12 голосов
/ 18 мая 2010

Не думаю, что я бы сказал, что он «кешируется» как таковой, но он просто хранится в поле, поэтому достаточно быстр для частых вызовов.

Реализация Sun JDK size() просто:

public int size() {
    return size;
}
4 голосов
/ 18 мая 2010

Да.

Быстрый взгляд на исходный код Java скажет вам ответ.

2 голосов
/ 18 мая 2010

Это реализация в OpenJDK версии :

/**
 * Returns the number of elements in this list.
 *
 * @return the number of elements in this list
 */
public int size() {
    return size;
}

Так что это так же хорошо, как вызов метода. Маловероятно, что HotSpot кэширует значение, возвращаемое этим методом, поэтому, если вы действительно THAT , вы можете кэшировать его самостоятельно. Если ваше профилирование не показало, что это узкое место, хотя (не очень вероятно), вам следует просто позаботиться о читабельности, а не о том, кэшируется ли простой вызов метода, который возвращает значение поля.

2 голосов
/ 18 мая 2010

Я точно не знаю ответа, но думаю, что нет.Компилятор Java, если не считать специального массива ArrayList, не может знать, что вызываемые вами функции не будут мутировать, и что в результате вызов size () должен возвращать то же значение.Поэтому я считаю крайне маловероятным, что компилятор Java будет учитывать повторяющиеся вызовы size () и сохранять их во временном значении.Если вам нужен этот уровень оптимизации, вы должны сами хранить значение в локальной переменной.В противном случае, да, вы будете платить за накладные расходы при вызове функции, связанные с вызовом метода size ().Обратите внимание, что метод size () для ArrayList равен O (1) (хотя накладные расходы на вызов функции довольно большие).Лично я бы исключил любые вызовы size () из циклов и вручную сохранил бы их в локальном, где это применимо.

Редактировать Даже если такая оптимизация не может быть выполнена компилятором Java, было точно указано, что JIT может встроить реализацию ArrayList.size () так, что она стоит столько же, сколько и доступ к полю, без каких-либо дополнительных затрат на вызов методаТаким образом, в действительности затраты незначительны, хотя вы все равно могли бы немного сэкономить, сохранив вручную во временном хранилище (что может исключить поиск в памяти и вместо этого подать переменную из регистра ЦП).

0 голосов
/ 18 мая 2010

Если кэширование результата метода size() заметно улучшит производительность (что иногда происходит - я регулярно вижу ArrayList.size() в качестве верхнего скомпилированного метода в моих -Xprof выходных данных), тогда рассмотрите возможность преобразования всего списка в массив для еще большего ускорения.

Вот одна хитрость, которая может сработать, если вы регулярно просматриваете список, но обновляете его очень редко:

class FooProcessor {

    private Foo[] fooArray = null;
    private List<Foo> fooList = new ArrayList<Foo>();

    public void addFoo(Foo foo) {
       fooList.add(foo);
       fooArray = null;
    }

    public void processAllFoos() {
        Foo[] foos = getFooArray();
        for (int i = 0; i < foos.length; ++ i) {
            process(foos[i]);
        }
    }

    private void getFooArray() {
        if (fooArray == null) {
            Foo[] tmpArray = new Foo[fooList.size()];
            fooArray = fooList.toArray(tmpArray);
        }
        return fooArray;
    }

}
0 голосов
/ 18 мая 2010

Зачем это нужно? В конце концов, ArrayList реализует интерфейс List, который поддерживается массивом.

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

Однако я не смотрел больше, чем на документы по API.

0 голосов
/ 18 мая 2010

Очевидная реализация ArrayList - хранить размер внутри поля. Я был бы очень удивлен, если бы он когда-либо был вычислен, даже после изменения размера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...