[英]Why is Java Vector (and Stack) class considered obsolete or deprecated?
為什么 Java Vector 被視為遺留類、已過時或已棄用?
使用並發時它的使用是否有效?
如果我不想手動同步對象而只想使用線程安全集合而不需要制作底層數組的新副本(就像CopyOnWriteArrayList
所做的那樣),那么使用Vector
可以嗎?
Stack
是Vector
的子類,我應該用什么代替它呢?
Vector
在每個單獨的操作上同步。 那幾乎從來都不是您想要做的。
通常,您希望同步整個操作序列。 同步單個操作既不太安全(例如,如果您迭代Vector
,您仍然需要取出鎖以避免其他人同時更改集合,這會在迭代線程中導致ConcurrentModificationException
)而且更慢(一次就夠了,為什么要反復取出鎖)?
當然,即使您不需要,它也有鎖定的開銷。
基本上,在大多數情況下,這是一種非常有缺陷的同步方法。 正如Brian Henk 先生所指出的,您可以使用諸如Collections.synchronizedList
之類的調用來裝飾集合——事實上, Vector
將“調整大小的數組”集合實現與“同步每個操作”位結合在一起,這是糟糕設計的另一個例子; 裝飾方法提供了更清晰的關注點分離。
至於Stack
等價物——我會從Deque
/ ArrayDeque
開始。
Vector 是 1.0 的一部分——最初的實現有兩個缺點:
1. 命名:向量實際上只是可以作為數組訪問的列表,所以它應該被稱為ArrayList
(它是Vector
的 Java 1.2 Collections 替代品)。
2. 並發性:所有的get()
、 set()
方法都是synchronized
的,所以你不能對同步進行細粒度的控制。
ArrayList
和Vector
之間沒有太大區別,但您應該使用ArrayList
。
來自 API 文檔。
從 Java 2 平台 v1.2 開始,這個類被改造以實現 List 接口,使其成為 Java Collections Framework 的成員。 與新的集合實現不同,Vector 是同步的。
Vector除了上面已經給出的使用Vector的答案外,Vector還有一堆與List接口不同的枚舉和元素檢索方法,開發者(尤其是Java 1.2之前學習過的)如果處於代碼。 盡管枚舉速度更快,但它們不會檢查集合是否在迭代期間被修改,這可能會導致問題,並且考慮到可能會選擇 Vector 進行同步 - 伴隨着來自多個線程的訪問,這使其成為一個特別有害的問題。 使用這些方法還會將大量代碼耦合到 Vector,這樣就不容易用不同的 List 實現替換它。
您可以使用java.util.Collection
的synchronizedCollection/List方法從非線程安全集合中獲取線程安全集合。
java.util.Stack
繼承了java.util.Vector
的同步開銷,這通常是不合理的。
不過,它繼承的遠不止這些。 java.util.Stack extends java.util.Vector
這一事實是面向對象設計中的一個錯誤。 純粹主義者會注意到,除了傳統上與堆棧相關的操作(即:push、pop、peek、size)之外,它還提供了許多方法。 還可以執行search
、 elementAt
、 setElementAt
、 remove
和許多其他隨機訪問操作。 基本上由用戶決定是否使用Stack
的非堆棧操作。
出於這些性能和 OOP 設計原因, java.util.Stack
的 JavaDoc推薦ArrayDeque
作為自然替代品。 (雙端隊列不僅僅是堆棧,但至少它僅限於操縱兩端,而不是提供對所有內容的隨機訪問。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.