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

Используется ли метод ArrayList.size()?

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

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

Я прав?

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

4b9b3361

Ответ 1

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

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

public int size() {
    return size;
}

Ответ 2

Да.

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

Ответ 3

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

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

Ответ 4

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

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

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

Ответ 5

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

Ответ 6

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

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

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

Ответ 7

Если кеширование результата метода 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;
    }

}