Чому клас класу Java Vector (і Stack) вважається застарілим або застарілим?


677

Чому Java Vector вважається застарілим класом, застарілим або застарілим?

Чи не застосовується його використання при роботі з одночасністю?

І якщо я не хочу вручну синхронізувати об'єкти і просто хочу використовувати безпечну для колекції колекцію без необхідності робити свіжі копії базового масиву (як CopyOnWriteArrayListце робиться), то це добре використовувати Vector?

Що про те Stack, що є підкласом Vector, що я повинен використовувати замість нього?


Вони застаріли, але не застаріли.
Маркіз Лорн

Відповіді:


655

Vectorсинхронізується на кожній окремій операції. Це майже ніколи те, що ви хочете зробити.

Як правило, ви хочете синхронізувати цілу послідовність операцій. Синхронізація окремих операцій є і менш безпечною (наприклад, якщо ви повторюєте Vector, наприклад, вам все одно потрібно зняти замок, щоб уникнути того, щоб хтось міняв колекцію одночасно, що призведе ConcurrentModificationExceptionдо ітераційного потоку), але також повільніше ( навіщо брати замок повторно, коли одного разу буде достатньо)?

Звичайно, він також має накладні витрати, навіть коли вам цього не потрібно.

В основному, це дуже хибний підхід до синхронізації в більшості ситуацій. Як зазначав містер Брайан Хенк , ви можете прикрасити колекцію, використовуючи такі дзвінки, як Collections.synchronizedList- той факт, що Vectorпоєднує в собі реалізацію колекції "зміненого масиву" та біт "синхронізувати кожну операцію", є ще одним прикладом поганого дизайну; підхід до декорування дає більш чітке розділення проблем.

Що стосується Stackеквівалента - я б дивився Deque/ ArrayDequeдля початку.


108
"Як правило, ви хочете синхронізувати цілу послідовність операцій." - У цьому справа! Дякую!
fjsj

7
в якій версії Java застарілий вектор (В даний час я використовував Java7). Але я ніколи не бачу як застарілий? До побачення приємне Пояснення ... + 1
Самір Мангролія

17
@Samir: Це офіційно не застаріло - це просто те, що ArrayList, як правило, кращий.
Джон Скіт

26
@Samir: Ні, я не збираюся намагатися передбачити майбутнє.
Джон Скіт

5
просто гр8. вектор не рекомендується його спадщина class.There повинна бути різницею між застарілим і застарілим і так є бачити stackoverflow.com/questions/2873254 / ...
Prashant Shilimkar

82

Вектор був частиною 1,0 - початкова реалізація мала два недоліки:

1. Іменування: вектори насправді є лише списками, до яких можна отримати доступ як масиви, тому його слід було викликати ArrayList(для чого це заміна Java 1.2 Collections Vector).

2. Паралельність: Все з get(), set()методи synchronized, так що ви не можете мати дрібнозернистий контроль над синхронізацією.

Різниця між ArrayListі Vector, але не дуже , але вам слід скористатися ArrayList.

Від док. API

Як і на платформі Java 2 v1.2, цей клас був дооснащений для реалізації інтерфейсу List, завдяки чому він став членом Java Collections Framework. На відміну від нових реалізацій колекції, вектор синхронізований.


Списки, до яких можна отримати доступ до масивів? ArrayList - не дуже коротке або привабливе ім'я, тому вектор може бути використаний в інших місцях (наприклад, STL).
безтурботний

6
@dhardy Список з масивом як його основна реалізація. Там же ArrayList, LinkedListі т.д., всі з яких реалізує інтерфейс List, так що якщо ви хочете використовувати Listметоди , не знаючи , що основна реалізація на насправді ви можете просто взяти в Listякості параметра методів і т.д. Те ж саме відноситься до реалізаторів Mapі так далі. Тим часом, у C ++ є std::arrayклас, який є лише заміною на основі шаблонів для масивів статичної довжини у стилі C.
JAB

41

Окрім уже заявлених відповідей щодо використання Vector, Vector також має безліч методів навколо перерахування та пошуку елементів, які відрізняються від інтерфейсу List, і розробники (особливо ті, хто вивчав Java до 1.2), як правило, можуть використовувати їх, якщо вони знаходяться в код. Хоча перерахування швидше, вони не перевіряють, чи колекція була змінена під час ітерації, що може спричинити проблеми, а враховуючи, що вектор може бути обраний для його синхронізації - із супутнім доступом з декількох потоків, це робить це особливо згубною проблемою. Використання цих методів також підключає багато коду до Vector, так що замінити його на іншу реалізацію списку буде непросто.


14

Ви можете скористатися методом синхронізованогоjava.util.Collection збирання / списку, щоб отримати колекцію, захищену від потоку, із безпечної для потоку.


2
чому це краще, ніж вектор?
fjsj

8
Як згадував Джон, Vector не буде працювати так само добре, і цей метод дозволяє вам вибрати, коли його гарна ідея зробити синхронізацію. Це повністю питання дизайну. Ви повинні використовувати ArrayList over Vector, оскільки вам слід за замовчуванням мати несинхронізований доступ.
Брайан Хенк

Як це відповідає на питання?
Маркіз Лорн

8

java.util.Stackуспадковує накладні витрати синхронізації java.util.Vector, що зазвичай не виправдано.

Хоча це успадковує набагато більше, ніж це. Те, що java.util.Stack extends java.util.Vectorє помилкою в об'єктно-орієнтованому дизайні. Пуристи зазначають, що він також пропонує безліч методів поза операціями, традиційно пов'язаними зі стеком (а саме: push, pop, peek, size). Це також можна зробити search, elementAt, setElementAt, remove, і багато інших операцій з довільним доступом. В основному, користувач повинен утримуватися від використання операцій без стека операцій Stack.

З цих причин продуктивності та дизайну OOP, JavaDocjava.util.Stack рекомендує ArrayDequeяк природну заміну. (Деке - це більше, ніж стек, але принаймні обмежується маніпулюванням двох кінців, а не пропонуванням випадкового доступу до всього.)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.