Saya membutuhkan Stack
struktur data untuk kasus penggunaan saya. Saya harus bisa mendorong item ke dalam struktur data dan saya hanya ingin mengambil item terakhir dari Stack. The javadoc untuk Stack mengatakan:
Serangkaian operasi stack LIFO yang lebih lengkap dan konsisten disediakan oleh antarmuka Deque dan implementasinya, yang harus digunakan sebagai preferensi untuk kelas ini. Sebagai contoh:
Deque<Integer> stack = new ArrayDeque<>();
Saya pasti tidak ingin perilaku tersinkronisasi di sini karena saya akan menggunakan datastructure ini ke metode lokal. Terlepas dari ini, mengapa saya lebih suka Deque
di Stack
sini?
PS: Javadoc dari Deque mengatakan:
Deques juga dapat digunakan sebagai tumpukan LIFO (Last-In-First-Out). Antarmuka ini harus digunakan sebagai preferensi untuk kelas Stack legacy.
sumber
Jawaban:
Untuk satu hal, itu lebih masuk akal dalam hal warisan. Fakta yang
Stack
meluasVector
benar-benar aneh, dalam pandangan saya. Di awal Jawa, pewarisan IMO terlalu sering digunakan -Properties
menjadi contoh lain.Bagi saya, kata penting dalam dokumen yang Anda kutip konsisten .
Deque
memperlihatkan serangkaian operasi yang semuanya tentang kemampuan untuk mengambil / menambah / menghapus item dari awal atau akhir koleksi, iterate dll - dan hanya itu. Sengaja tidak ada cara untuk mengakses elemen dengan posisi, yangStack
mengekspos karena itu adalah subkelas dariVector
.Oh, dan juga
Stack
tidak memiliki antarmuka, jadi jika Anda tahu Anda perluStack
operasi, Anda akhirnya berkomitmen ke kelas konkret tertentu, yang biasanya bukan ide yang baik.Juga seperti yang ditunjukkan dalam komentar,
Stack
danDeque
memiliki perintah iterasi terbalik:yang juga dijelaskan dalam JavaDocs for Deque.iterator () :
sumber
LinkedList
, tetapiArrayDequeue
akan (sering) menjadi lebih cepat. Jika Anda ingin perilaku stack, Anda bisa menggunakanStack
tetapiArrayDeque
akan (sering) lebih cepat.Stack
memiliki masalah eksposur rep, tetapi jika saya ingin struktur data stack saya ingin dapat memanggil metode seperti push, pop, dan mengintip, dan bukan hal-hal yang harus lakukan dengan ujung tumpukan lainnya.Ini adalah interpretasi saya tentang inkonsistensi yang disebutkan dalam deskripsi kelas Stack.
Jika Anda melihat Implementasi Tujuan Umum di sini - Anda akan melihat ada pendekatan yang konsisten untuk implementasi set, peta, dan daftar.
Untuk mengatur dan memetakan kami memiliki 2 implementasi standar dengan peta hash dan pohon. Yang pertama paling banyak digunakan dan yang kedua digunakan ketika kita membutuhkan struktur yang dipesan (dan juga mengimplementasikan antarmuka sendiri - SortedSet atau SortedMap).
Kami dapat menggunakan gaya pernyataan yang disukai seperti
Set<String> set = new HashSet<String>();
melihat alasan di sini .Tetapi kelas Stack: 1) tidak memiliki antarmuka sendiri; 2) adalah subkelas dari kelas Vector - yang didasarkan pada array yang dapat diubah ukurannya; jadi di mana penerapan daftar tertaut dari stack?
Dalam antarmuka Deque kami tidak memiliki masalah seperti itu termasuk dua implementasi (array yang dapat diubah-ubah - ArrayDeque; daftar tertaut - LinkedList).
sumber
Satu lagi alasan untuk menggunakan Dequeue over Stack adalah Dequeue memiliki kemampuan untuk menggunakan stream convert to list dengan menjaga konsep LIFO diterapkan sementara Stack tidak.
sumber
Berikut adalah beberapa alasan mengapa Deque lebih baik daripada Stack:
Desain berorientasi objek - Warisan, abstraksi, kelas dan antarmuka: Stack adalah sebuah kelas, Deque adalah sebuah antarmuka. Hanya satu kelas yang dapat diperluas, sedangkan sejumlah antarmuka dapat diimplementasikan oleh satu kelas di Jawa (multiple inheritance of type). Menggunakan antarmuka Deque menghilangkan ketergantungan pada kelas Stack beton dan leluhurnya dan memberi Anda lebih banyak fleksibilitas, misalnya kebebasan untuk memperluas kelas yang berbeda atau menukar implementasi Deque yang berbeda (seperti LinkedList, ArrayDeque).
Inkonsistensi: Stack memperluas kelas Vector, yang memungkinkan Anda untuk mengakses elemen dengan indeks. Ini tidak konsisten dengan apa yang seharusnya dilakukan oleh Stack, itulah mengapa antarmuka Deque lebih disukai (tidak memungkinkan operasi semacam itu) - operasi yang diizinkan konsisten dengan apa yang harus diizinkan oleh struktur data FIFO atau LIFO.
Kinerja: Kelas vektor yang diperluas Stack pada dasarnya adalah versi "thread-safe" dari ArrayList. Sinkronisasi berpotensi menyebabkan hit kinerja signifikan ke aplikasi Anda. Juga, memperluas kelas-kelas lain dengan fungsi yang tidak dibutuhkan (seperti yang disebutkan dalam # 2) mengasapi objek Anda, berpotensi menghabiskan banyak memori tambahan dan overhead kinerja.
sumber
Bagi saya poin spesifik ini tidak ada: Stack adalah Threadsafe karena berasal dari Vector, sedangkan implementasi deque paling tidak, dan dengan demikian lebih cepat jika Anda hanya menggunakannya dalam satu utas.
sumber
Kinerja mungkin menjadi alasan. Algoritma yang saya gunakan turun dari 7,6 menit menjadi 1,5 menit dengan hanya mengganti Stack dengan Deque.
sumber
Deque digunakan adalah situasi di mana Anda ingin mengambil elemen dari kepala dan ekor. Jika Anda ingin tumpukan sederhana tidak perlu pergi untuk deque.
sumber