Какова цель векторного потенциала - PullRequest
8 голосов
/ 07 мая 2010

Vector API определяет 4 различных конструктора:

Vector()

Vector(Collection<? extends E> c)

Vector(int initialCapacity)

Vector(int initialCapacity, int capacityIncrement)

но как они работают и для чего они используются? Почему я должен определить фиксированную емкость для вектора? Даже если я установлю начальную емкость на 100, я могу добавить 101 элемент к вектору:

Vector<Object> test = new Vector<Object>(100);
for (int i = 0; i < 100; i++) {
    test.add(new Object());
}

test.add(new Object());
System.out.println(test.size());
System.out.println(test.capacity());

В приведенном выше коде второй sysout (test.capacity ()) записывает 200. Почему емкость в этом векторе 200? Начальная емкость равна 100, и я не определил прирост емкости.

Мне действительно интересно, есть ли какой-нибудь реальный пример использования этих constrcutors?

И знакомый вопрос: В чем разница между Vector.get (int position) и Vector.elementAt (int position)? Я прочитал, что метод get был определен до того, как Vector был добавлен в класс Collection, и поэтому было необходимо добавить метод elementAt (int position) позже. Это правда? Или есть другие отличия?

Ответы [ 2 ]

22 голосов
/ 07 мая 2010

Что такое "начальная" емкость?

Начальная емкость - это просто емкость Vector во время строительства.

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

Вот выдержка из Vector API :

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

Обратите внимание, что после постройки вы также можете использовать ensureCapacity для достижения того же эффекта.

Смотри также


Почему это важно?

Скажем, например, у вас есть 100 элементов, которые вы хотите вставить в Vector. Нулевой конструктор устанавливает Vector на первоначальную емкость 10 и удваивается при росте. Это означает, что для размещения 100 элементов потребуется удвоение до 20, 40, 80, а затем, наконец, до 160, прежде чем он сможет вместить все 100 элементов.

Обратите внимание, что было выполнено 4 шага инкрементного перераспределения, и когда он, наконец, соответствует всем 100 элементам, используется только 60% фактической емкости. С другой стороны, ensureCapacity(100) (или использование соответствующей перегрузки конструктора для достижения того же эффекта) перед вставкой сделало бы процесс более эффективным, так как нет избыточной неиспользуемой емкости, а массив только нужно перераспределить один раз.

Обратите внимание, что асимптотически, два вышеупомянутых процесса одинаково оптимальны (O(N) время и O(N) пространство), но, конечно, последний является постоянным улучшением по сравнению с первым в обоих пространство и время.

Конечно, если вы установите ensureCapacity(10000000) и вставите только 100 элементов, вы будете использовать только 0,001% емкости - что за пустая трата! Так что, если вы заранее знаете, сколько элементов вы собираетесь вставить, вы можете сделать процесс более эффективным (с постоянным коэффициентом), используя ensureCapacity, но в любом случае Vector по-прежнему отлично справляется со своей задачей. даже без вашей помощи.

Смотри также


Зачем удваивать?

Не вдаваясь в подробности, это удвоение роста является формой геометрического расширения, что позволило проводить амортизированный анализ в постоянном времени на одну операцию для Vector. Стоит отметить, что ArrayList, похожая растущая структура данных, поддерживаемая массивом, даже не определяет детали своей политики роста, но OpenJDK версия имеет фактор роста 3/2.

Обратите внимание, что Vector фактически позволяет вам установить негеометрический коэффициент роста с помощью capacityIncrement. Важно понимать, что если вы установите для capacityIncrement небольшое ненулевое значение, вы фактически можете заставить Vector выполнять ужасные асимптотически . Например, если вы установите значение 1, то добавление элементов N будет O(N^2) операцией!

ArrayList не позволяет вам настраивать его политику роста, поскольку вы даже не должны знать (ни заботиться, правда!).

Смотри также


Разное

А как насчет elementAt и get?

Прямо с Документация :

Начиная с платформы Java 2 v1.2, этот класс был модифицирован для реализации интерфейса List, что сделало его членом Java Collections Framework .В отличие от новых реализаций коллекции, Vector - это synchronized.

public E elementAt(int index): возвращает компонент по указанному индексу.Этот метод идентичен по функциональности методу get(int) (который является частью интерфейса List).

Таким образом, в хронологическом порядке Vector имел elementAt, прежде чем его модернизировали для реализацииList, и, следовательно, должен реализовывать get.

Обратите внимание на часть о Vector, являющейся synchronized.Если вам не нужна эта функция, ArrayList будет гораздо лучшим выбором, так как вы не платите за безопасность потоков.

См. Также

3 голосов
/ 07 мая 2010

Если указать нулевое или отрицательное приращение емкости, емкость вектора удваивается каждый раз, как указано в документации для поля capacityIncrement:

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

Если вы указываете только емкость, по умолчанию capacityIncrement равен нулю - отсюда и поведение удвоения.

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

Что касается get и elementAt() - да, elementAt() был добавлен для общего API коллекций. Глядя на реализацию, они идентичны, кроме точных деталей исключения, которое выдается в случае ошибки.

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