1. Обзор
В этом уроке мы сосредоточимся на различиях между классами ArrayList
и Vector
. Оба они относятся к Java Collections Framework и реализуют интерфейс java.util.List .
Однако эти классы имеют существенные различия в своих реализациях.
2. Что изменилось?
Для начала представим основные отличия ArrayList
и Vector.
Затем мы обсудим некоторые моменты более подробно:
- синхронизация — первое существенное различие между этими двумя.
Vector
синхронизирован, аArrayList
— нет. - рост размера. Еще одно различие между ними заключается в том, как они изменяют размер при достижении своей емкости. Вектор
удваивает
свой размер. Напротив,ArrayList
увеличивается только на половину своей длины. - итерация — и
Vector
может использоватьIterator
иEnumeration
для обхода элементов. С другой стороны,ArrayList
может использовать толькоIterator
. - производительность — во многом из-за синхронизации
векторные
операции выполняются медленнее по сравнению сArrayList.
- framework — Кроме того,
ArrayList
является частью каркаса коллекций и был представлен в JDK 1.2. Между тем,Vector
присутствует в более ранних версиях Java как унаследованный класс.
3. Вектор
Поскольку у нас уже есть расширенное руководство по **ArrayList,
** мы не будем здесь обсуждать его API и возможности. С другой стороны, мы представим некоторые основные сведения о Vector
. ** ``** ``
Проще говоря ,
вектор представляет собой массив с изменяемым размером
. Он может увеличиваться и уменьшаться по мере добавления или удаления элементов.
Мы можем создать вектор обычным способом:
Vector<String> vector = new Vector<>();
Конструктор по умолчанию создает пустой вектор
с начальной емкостью 10.
Добавим несколько значений:
vector.add("foreach");
vector.add("Vector");
vector.add("example");
И, наконец, давайте пройдемся по значениям с помощью интерфейса Iterator
:
Iterator<String> iterator = vector.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
// ...
}
Или мы можем пройти по вектору
, используя Enumeration
:
Enumeration e = vector.elements();
while(e.hasMoreElements()) {
String element = e.nextElement();
// ...
}
Теперь давайте более подробно рассмотрим некоторые из их уникальных особенностей.
4. Параллелизм
Мы уже упоминали, что ArrayList
и Vector
отличаются своей стратегией параллелизма, но давайте рассмотрим ее подробнее. Если бы мы углубились в сигнатуры методов Vector
, то увидели бы, что каждая из них имеет ключевое слово synchronized:
public synchronized E get(int index)
Проще говоря, это означает, что только один поток может получить доступ к данному вектору в каждый момент времени .
На самом деле, эта синхронизация на уровне операции в любом случае должна быть наложена на нашу собственную синхронизацию для составных операций.
Напротив, ArrayList
использует другой подход. Его методы не
синхронизированы, и эта проблема разделена на классы, предназначенные для параллелизма.
Например, мы можем использовать CopyOnWriteArrayList
или Collections.synchronizedList
, чтобы получить эффект, аналогичный Vector
:
vector.get(1); // synchronized
Collections.synchronizedList(arrayList).get(1); // also synchronized
5. Производительность
Как мы уже говорили выше, Vector
синхронизируется, что напрямую влияет на производительность .
Чтобы увидеть разницу в производительности между операциями Vector
и ArrayList
, давайте напишем простой тест производительности JMH .
В прошлом мы рассматривали временную сложность операций ArrayList ,
поэтому давайте добавим тестовые примеры для Vector.
Во- первых
, давайте протестируем метод get()
:
@Benchmark
public Employee testGet(ArrayListBenchmark.MyState state) {
return state.employeeList.get(state.employeeIndex);
}
@Benchmark
public Employee testVectorGet(ArrayListBenchmark.MyState state) {
return state.employeeVector.get(state.employeeIndex);
}
Мы настроим JMH на использование трех потоков и 10 итераций прогрева.
И давайте сообщим среднее время на операцию на уровне наносекунд:
Benchmark Mode Cnt Score Error Units
ArrayListBenchmark.testGet avgt 20 9.786 ± 1.358 ns/op
ArrayListBenchmark.testVectorGet avgt 20 37.074 ± 3.469 ns/op
Мы видим, что ArrayList#get
работает примерно в три раза быстрее, чем Vector#get
.
Теперь давайте сравним результаты операции contains() :
@Benchmark
public boolean testContains(ArrayListBenchmark.MyState state) {
return state.employeeList.contains(state.employee);
}
@Benchmark
public boolean testContainsVector(ArrayListBenchmark.MyState state) {
return state.employeeVector.contains(state.employee);
}
И распечатайте результаты:
Benchmark Mode Cnt Score Error Units
ArrayListBenchmark.testContains avgt 20 8.665 ± 1.159 ns/op
ArrayListBenchmark.testContainsVector avgt 20 36.513 ± 1.266 ns/op
Как мы видим, для операции contains()
время выполнения для Vector
намного больше, чем для ArrayList
.
6. Резюме
В этой статье мы рассмотрели различия между классами Vector
и ArrayList
в Java. Кроме того, мы также более подробно представили векторные функции.
Как обычно, полный код для этой статьи доступен на GitHub .