Mengapa kelas Java Vector (dan Stack) dianggap usang atau usang?

677

Mengapa Java Vector dianggap sebagai kelas warisan, usang atau usang?

Bukankah penggunaannya valid ketika bekerja dengan concurrency?

Dan jika saya tidak ingin menyinkronkan objek secara manual dan hanya ingin menggunakan koleksi thread-safe tanpa perlu membuat salinan baru dari array yang mendasarinya (seperti CopyOnWriteArrayListhalnya), maka apakah boleh digunakan Vector?

Bagaimana dengan Stack, yang merupakan subkelas dari Vector, apa yang harus saya gunakan daripada itu?

fjsj
sumber
Mereka usang, tetapi mereka tidak ditinggalkan.
Marquis of Lorne

Jawaban:

655

Vectordisinkronkan pada setiap operasi individu. Itu hampir tidak pernah ingin Anda lakukan.

Secara umum Anda ingin menyinkronkan seluruh urutan operasi. Menyinkronkan masing-masing operasi kurang aman (jika Anda beralih pada Vector, misalnya, Anda masih perlu mengeluarkan kunci untuk menghindari orang lain mengubah koleksi pada saat yang sama, yang akan menyebabkan a ConcurrentModificationExceptiondi utas pengulangan) tetapi juga lebih lambat ( mengapa mengambil kunci berulang kali ketika sekali sudah cukup)?

Tentu saja, itu juga memiliki penguncian bahkan ketika Anda tidak perlu.

Pada dasarnya, ini adalah pendekatan yang sangat cacat untuk sinkronisasi dalam sebagian besar situasi. Seperti yang ditunjukkan oleh Tuan Brian Henk , Anda dapat menghias koleksi menggunakan panggilan seperti Collections.synchronizedList- fakta yang Vectormenggabungkan implementasi koleksi "array yang diubah ukurannya" dengan bit "sinkronisasi setiap operasi" adalah contoh lain dari desain yang buruk; pendekatan dekorasi memberikan pemisahan keprihatinan yang lebih bersih.

Adapun Stacksetara - saya akan melihat Deque/ ArrayDequemulai dengan.

Jon Skeet
sumber
108
"Umumnya Anda ingin menyinkronkan seluruh urutan operasi." - Itu intinya! Terima kasih!
fjsj
7
di mana versi java Deprecated Vector (Saat ini saya menggunakan Java7). Tapi saya tidak pernah melihat sebagai Deprecated? Bye the Way Penjelasan bagus ... + 1
Samir Mangroliya
17
@ Samir: Ini tidak secara resmi ditinggalkan - hanya saja ArrayList umumnya disukai.
Jon Skeet
26
@ Samir: Tidak, saya tidak akan mencoba untuk memprediksi masa depan.
Jon Skeet
5
cukup gr8. vektor tidak ditinggalkan, ini adalah kelas warisan. Harus ada perbedaan antara usang dan warisan dan ya ada lihat stackoverflow.com/questions/2873254/…
Prashant Shilimkar
82

Vektor adalah bagian dari 1.0 - implementasi asli memiliki dua kelemahan:

1. Penamaan: vektor benar-benar hanya daftar yang dapat diakses sebagai array, sehingga seharusnya dipanggil ArrayList(yang merupakan pengganti Java 1.2 Collections untuk Vector).

2. Concurrency: Semua get(), set()metode yang synchronized, sehingga Anda tidak dapat memiliki berbutir halus kontrol atas sinkronisasi.

Tidak ada banyak perbedaan antara ArrayListdan Vector, tetapi Anda harus menggunakannya ArrayList.

Dari dokumen API.

Pada platform Java 2 v1.2, kelas ini dipasang untuk mengimplementasikan antarmuka Daftar, menjadikannya anggota Java Collections Framework. Berbeda dengan implementasi koleksi baru, Vector disinkronkan.

Justin
sumber
Daftar yang dapat diakses sebagai array? ArrayList bukan nama yang sangat pendek atau menarik, yang mungkin menjadi alasan mengapa vektor digunakan di tempat lain (misalnya STL).
dhardy
6
@dhardy List dengan array sebagai implementasi yang mendasarinya. Ada ArrayList, LinkedList, dll, yang semuanya menerapkan antarmuka List, jadi jika Anda ingin memanfaatkan Listmetode tanpa harus mengetahui apa yang mendasari pelaksanaan sebenarnya Anda hanya dapat mengambil Listsebagai parameter untuk metode, dll yang sama berlaku untuk pelaksana Mapdan seterusnya. Sementara itu, C ++ memang memiliki std::arraykelas, yang hanya pengganti berbasis template untuk array panjang statis C-style.
JAB
41

Selain jawaban yang sudah dinyatakan tentang penggunaan Vektor, Vektor juga memiliki banyak metode seputar pencacahan dan pengambilan elemen yang berbeda dari antarmuka Daftar, dan pengembang (terutama mereka yang mempelajari Java sebelum 1.2) dapat cenderung menggunakannya jika mereka berada di kode. Meskipun Pencacahan lebih cepat, mereka tidak memeriksa apakah koleksi telah diubah selama iterasi, yang dapat menyebabkan masalah, dan mengingat bahwa Vector mungkin dipilih untuk sinkronisasi - dengan akses yang hadir dari beberapa utas, ini membuatnya menjadi masalah yang sangat berbahaya. Penggunaan metode ini juga memasangkan banyak kode ke Vector, sehingga tidak akan mudah untuk menggantinya dengan implementasi Daftar yang berbeda.

Yishai
sumber
14

Anda dapat menggunakan synchronizedCollection / Daftar metode java.util.Collectionuntuk mendapatkan koleksi benang-aman dari satu non-benang-aman.

Brian Henk
sumber
2
mengapa ini lebih baik daripada vektor?
fjsj 06
8
Seperti yang disebutkan oleh Jon, Vector tidak akan bekerja dengan baik, dan metode ini memungkinkan Anda untuk memilih kapan ide yang baik untuk melakukan sinkronisasi. Ini benar-benar masalah desain. Anda harus menggunakan ArrayList melalui Vector karena Anda seharusnya menggunakan akses non-sinkronisasi.
Brian Henk
Bagaimana ini menjawab pertanyaan?
Marquis of Lorne
8

java.util.Stackmewarisi overhead sinkronisasi java.util.Vector, yang biasanya tidak dibenarkan.

Ini mewarisi lebih banyak dari itu. Fakta itu java.util.Stack extends java.util.Vectoradalah kesalahan dalam desain berorientasi objek. Purist akan mencatat bahwa ia juga menawarkan banyak metode di luar operasi yang secara tradisional dikaitkan dengan stack (yaitu: push, pop, peek, size). Ini juga mungkin untuk melakukan search, elementAt, setElementAt, remove, dan banyak operasi random-akses lainnya. Pada dasarnya terserah kepada pengguna untuk menahan diri dari menggunakan operasi non-stack Stack.

Untuk alasan kinerja dan desain OOP ini, JavaDoc untukjava.util.Stack merekomendasikan ArrayDequesebagai pengganti alami. (Deque lebih dari sekadar tumpukan, tapi setidaknya itu terbatas untuk memanipulasi kedua ujungnya, daripada menawarkan akses acak ke semuanya.)

200_sukses
sumber