Почему класс Java Vector (и Stack) считается устаревшим или устаревшим?

Почему Java Vector считается устаревшим классом, устаревшим или устаревшим?

Разве его нельзя использовать при работе с параллелизмом?

И если я не хочу вручную синхронизировать объекты и просто хочу использовать потокобезопасную коллекцию без необходимости делать свежие копии базового массива (как это делает CopyOnWriteArrayList), тогда можно ли использовать Vector?

А как насчет Stack, который является подклассом Vector, что мне использовать вместо него?


person fjsj    schedule 06.09.2009    source источник
comment
Они устарели, но не устарели.   -  person user207421    schedule 08.04.2019


Ответы (5)


Vector синхронизируется по каждой отдельной операции. Это почти никогда не то, чем вы хотите заниматься.

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

Конечно, у него также есть накладные расходы на блокировку, даже когда вам это не нужно.

По сути, это очень ошибочный подход к синхронизации в большинстве ситуаций. Как заметил г-н Брайан Хенк, вы можете украсить коллекцию с помощью таких вызовов, как _ 4_ - еще один пример - тот факт, что Vector объединяет реализацию коллекции" массив с измененным размером "с битом" синхронизировать каждую операцию ". плохой дизайн; подход к декорированию дает более четкое разделение проблем.

Что касается эквивалента Stack - для начала я бы посмотрел на _7 _ / _ 8_.

person Jon Skeet    schedule 06.09.2009
comment
Обычно вы хотите синхронизировать всю последовательность операций. - В том-то и дело! Спасибо! - person fjsj; 07.09.2009
comment
в какой версии Java Deprecated Vector (в настоящее время я использовал Java7). Но я никогда не видел как устаревший? Пока, приятное объяснение ... +1 - person Samir Mangroliya; 09.03.2012
comment
@Samir: Официально он не устарел - просто ArrayList обычно предпочтительнее. - person Jon Skeet; 09.03.2012
comment
подскажите, в Будущем такое случится? - person Samir Mangroliya; 09.03.2012
comment
@Samir: Нет, я не буду пытаться предсказывать будущее. - person Jon Skeet; 09.03.2012
comment
@Jon Спасибо за объяснение. Одно небольшое исправление - например, утверждение, что если вы выполняете итерацию по вектору, вам все равно нужно снять блокировку, чтобы никто другой не изменил коллекцию одновременно, является только частично правильным - итератор выдаст исключение ConcurrentModificationException, чтобы избежать непредсказуемого поведения если это произойдет. - person Alex; 05.05.2013
comment
@Alex: Ну, я хотел сказать, что вы синхронизируете, чтобы избежать последствий попытки другого потока сделать это. Поясню. - person Jon Skeet; 05.05.2013
comment
@Alex: итератор попытается вызвать исключение. Однако это не гарантируется. Документы в основном говорят, что это просто помогает обнаруживать ошибки. Не надейтесь на это. - person cHao; 07.05.2013
comment
просто gr8. vector не является устаревшим, это устаревший класс. Должна быть разница между устаревшим и устаревшим, и да, есть см. stackoverflow.com/questions/2873254/ - person Prashant Shilimkar; 23.12.2013
comment
Есть ли ситуация, когда нам действительно нужно использовать Vector ?? - person Raja Asthana; 03.04.2014
comment
@RajaAsthana: Возможно, вы взаимодействуете с другим API, который его использует. Я не могу вспомнить, когда в последний раз видел это в свежем коде. - person Jon Skeet; 03.04.2014
comment
Я вижу много кода, особенно при добавлении ошибок, таких как errorVector.add (недопустимое имя). Надо ли этого избежать? - person Raja Asthana; 03.04.2014
comment
@RajaAsthana: Это действительно зависит от контекста. Где вы видите весь этот код? Это в какой-то устаревшей кодовой базе? - person Jon Skeet; 03.04.2014
comment
@RajaAsthana: Значит, именно поэтому вы, в основном, это видите. - person Jon Skeet; 03.04.2014
comment
@JonSkeet Последний раз, когда я вижу вектор в коде, это пример кода в Beginning JSP, JSF и Tomcat. Авторские права © 2012, Джулио Замбон. Я читаю это прямо сейчас. Теперь, после прочтения твоего поста, мне интересно, почему он до сих пор этим пользуется? Тем более, что он дает указания в начале книги по установке Java 7 SDK (и Tomcat 7). Что касается самого кода, он его использует из-за синхронизации ... - person Nenad Bulatovic; 18.06.2014
comment
@Nenad: Я не могу ответить на этот вопрос, но я бы не стал так поступать, если бы писал такую ​​книгу. - person Jon Skeet; 18.06.2014
comment
У Vector есть преимущество в виде короткого запоминающегося имени и его закрепления в C ++, с которого начинали многие программисты. Помимо (неэффективной) встроенной синхронизации с Vector, вы должны иметь возможность делать с ArrayList все, что вы могли бы делать с Vector, и, как правило, делать это быстрее. - person Androidcoder; 11.04.2015
comment
Я никогда не понимал, почему есть люди, которые называют некоторые части некоторых API мертвыми или устаревшими только потому, что они могут быть неэффективными. NEWSFLASH: почти все алгоритмы можно оптимизировать, многие из них неэффективны, но никто не называет это мертвым. Эффективность больше не важна, мы живем в 21 веке, поэтому, если вы не пишете высокопроизводительное встроенное программное обеспечение для космических шаттлов (ну, преемника), нет смысла разглагольствовать против API вроде этого - и даже тогда: разработчики программного обеспечения просто выбирают какую-то альтернативу, они не разглагольствуют, но пока не волнуются об этом :) - person specializt; 10.02.2016
comment
@specializt: Я думаю, что вполне разумно называть это устаревшим API, если есть альтернатива, которая явно лучше в большинстве ситуаций. Мало того, что Vector менее эффективна с точки зрения ненужной синхронизации, но, выполняя эту синхронизацию, она может создать иллюзию поточной безопасности для пользователей, которые плохо знакомы с потоками и думают, что синхронизации каждой операции достаточно для сделать безопасным произвольное использование между потоками. Я по-прежнему очень рад рекомендовать перейти с Vector на ArrayList почти во всех случаях. - person Jon Skeet; 10.02.2016
comment
в этом нет никакого смысла - разумно называть что-то устаревшим, если есть лучшие альтернативы? Возможно, вы захотите подумать об этом еще раз ... по этой причине практически все, что существует, является наследием - person specializt; 10.02.2016
comment
@specializt: Нет, я так не думаю. Ищем определение: наследие, соответствующее прилагательное для вычислительных состояний: обозначающее или относящееся к программному или аппаратному обеспечению, которое было заменено, но которое трудно заменить из-за его широкого использования. Звучит очень похоже на то, что я сказал. Обратите внимание, что в большинстве ситуаций лучше использовать довольно высокую планку - в то время как LinkedList<T> лучше, чем ArrayList<T> в некоторых ситуациях, часто верно обратное - ни один из них эффективно не осуждает другой. - person Jon Skeet; 10.02.2016
comment
@specializt: Кроме того, из JLS 9.6.4.6: программный элемент с аннотацией @Deprecated - это элемент, который программистам не рекомендуется использовать, обычно потому, что это опасно или потому что существует лучшая альтернатива. (Да, я знаю, что устаревшие и устаревшие - это не одно и то же слово, но здесь они часто используются как синонимы. Не то чтобы Vector официально устарел, заметьте ... точно так же, как Date и Calendar нет, но я тоже не хотел бы использовать их в новых разработках.) - person Jon Skeet; 10.02.2016
comment
.. так что он также устарел, потому что вы не хотите его использовать. Ройт. - person specializt; 10.02.2016
comment
@specializt: Я думаю, что на данном этапе нам придется соглашаться, чтобы не соглашаться. - person Jon Skeet; 10.02.2016
comment
Для обеспечения параллелизма мы можем использовать пакет java Concurrent. Однако мы можем написать код, который обращается к коллекции небезопасным для потоков способом. - person Hamedz; 08.06.2016
comment
@Jon Спасибо за хороший ответ. Что касается эквивалента Stack - для начала я бы посмотрел на _2 _ / _ 3_. Есть ли у Stack синхронизированные методы в качестве суперкласса Vector? Должны ли мы заменить Stack на Collections.synchronizedList применительно к Deque/ArrayDeque? - person ; 21.11.2017
comment
@Ben: Я бы ожидал, что любые вызовы в Stack в любом случае будут проходить через методы суперкласса, но мне нужно будет проверить, чтобы быть уверенным. - person Jon Skeet; 22.11.2017
comment
@specializt Эффективность больше не важна. Если бы эффективность не была важна для программистов нижнего уровня, она не могла быть неважной для высокопроизводительных парней. - person Dávid Horváth; 12.09.2020
comment
еще раз: кажется, что это не имеет никакого смысла. Эффективность больше не важна для кого-либо ... ну ... может быть, кроме разработчиков в реальном времени, которые работают над проектами для продуктов, которые ставят под угрозу или, возможно, спасают человеческие жизни - но это довольно небольшая подгруппа людей. Сокращение нескольких циклов процессора - дело далекого прошлого - это уже преодолено. Да, все мы знаем, что вы любите это делать, но это просто не нужно для разработки продукта; вы можете вставить итерацию оптимизации после выпуска, если так отчаянно хотите сделать ее быстрее. - person specializt; 19.09.2020
comment
@specializt Это может быть неважно на более высоких уровнях. Если вы разрабатываете службу REST для базы данных в Spring, это может быть неважно. Но если вы разрабатываете сам Spring или Hibernate, или базовый драйвер JDBC, или саму СУБД, или ядро ​​ОС, то нет. И даже на более высоком уровне современный мужчина не может терпеть даже крошечного перерыва в его / ее наиболее часто используемых приложениях. Производительность имеет значение. - person Dávid Horváth; 08.10.2020
comment
Я думаю, вы не понимаете разницы между прерыванием UX и (фоновой) производительностью - оба не нужно (фактически: не должны) подключаться - очень медленные фоновые / многопоточные алгоритмы не имеют никакого влияния на UX - следовательно, не имеет значения с точки зрения производительности. Если, конечно, ваши разработчики очень неопытны и не могут (или не захотят) отделить UI / UX от логики. Не волнуйтесь: вы сами убедитесь в этом в ближайшие годы. - person specializt; 15.10.2020
comment
@specializt Я вас не понимаю. Как здесь возникают плохо реализованные параллелизм и прерывания пользовательского интерфейса? Замораживание графики пользовательского интерфейса или медленное разрешение зависимостей пакетов само по себе может раздражать. В любом случае, мы должны остановиться или перейти в чат. - person Dávid Horváth; 25.12.2020
comment
Я думаю, вам следует заново пройти какой-то курс для начинающих по программированию, включая параллелизм и потоки пользовательского интерфейса / основные потоки ... и, возможно, поискать термин разрешение зависимостей, вы, кажется, перепутали здесь довольно много вещей. - person specializt; 01.01.2021

Vector был частью 1.0 - исходная реализация имела два недостатка:

1. Именование: векторы на самом деле представляют собой просто списки, к которым можно получить доступ как к массивам, поэтому его следовало называть ArrayList (который является заменой коллекций Java 1.2 для Vector).

2. Параллелизм: все get(), set() методы synchronized, поэтому вы не можете иметь точный контроль над синхронизацией.

Между ArrayList и Vector нет большой разницы, но вы должны использовать ArrayList.

Из документа API.

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

person Justin    schedule 06.09.2009
comment
Списки, к которым можно получить доступ в виде массивов? ArrayList - не очень короткое или запоминающееся имя, возможно, поэтому вектор используется в другом месте (например, в STL). - person dhardy; 06.05.2013
comment
@dhardy Список с массивом в качестве базовой реализации. Там ArrayList, LinkedList и т. Д., Все из которых реализуют интерфейс List, поэтому, если вы хотите использовать List методы, не зная, какова на самом деле основная реализация, вы можете просто взять List в качестве параметра методов и т. Д. то же самое относится к разработчикам Map и так далее. Между тем, в C ++ есть класс std::array, который является просто заменой на основе шаблонов массивов статической длины в стиле C. - person JAB; 14.05.2014

Помимо уже заявленных ответов об использовании Vector, Vector также имеет множество методов для перечисления и извлечения элементов, которые отличаются от интерфейса List, и разработчики (особенно те, кто изучал Java до 1.2) могут, как правило, использовать их, если они находятся в код. Хотя перечисления выполняются быстрее, они не проверяют, была ли коллекция изменена во время итерации, что может вызвать проблемы, и, учитывая, что вектор может быть выбран для ее синхронизации - с сопутствующим доступом из нескольких потоков, это делает эту проблему особенно опасной. Использование этих методов также связывает большой объем кода с Vector, так что заменить его другой реализацией List будет непросто.

person Yishai    schedule 06.09.2009

Вы можете использовать synchronizedCollection / List в java.util.Collection, чтобы получить поточно-безопасную коллекцию из небезопасной для потоков.

person Brian Henk    schedule 06.09.2009
comment
почему это лучше вектора? - person fjsj; 06.09.2009
comment
Как упоминал Джон, Vector не будет работать так же хорошо, и этот метод позволяет вам выбрать, когда лучше всего выполнять синхронизацию. Это полностью проблема дизайна. Вы должны использовать ArrayList вместо Vector, потому что вы должны по умолчанию использовать несинхронизированный доступ. - person Brian Henk; 06.09.2009
comment
Как это отвечает на вопрос? - person user207421; 08.04.2019

java.util.Stack наследует накладные расходы на синхронизацию java.util.Vector, что обычно не оправдано.

Однако он наследует гораздо больше. Дело в том, что java.util.Stack extends java.util.Vector - это ошибка объектно-ориентированного дизайна. Пуристы заметят, что он также предлагает множество методов помимо операций, традиционно связанных со стеком (а именно: push, pop, peek, size). Также возможно выполнение search, elementAt, setElementAt, remove и многие другие операции с произвольным доступом. По сути, пользователь должен воздерживаться от использования операций Stack, не связанных со стеком.

По этим причинам производительности и дизайна ООП JavaDoc для java.util.Stack < / a> рекомендует ArrayDeque в качестве естественной замены . (Двухсторонняя очередь - это больше, чем стек, но, по крайней мере, она ограничена манипулированием двумя сторонами, а не предлагает произвольный доступ ко всему.)

person 200_success    schedule 12.02.2016