ทำไมคลาส Java Vector (และ Stack) จึงถือว่าล้าสมัยหรือเลิกใช้แล้ว


677

เหตุใด Java Vector จึงถือเป็นคลาสดั้งเดิมล้าสมัยหรือเลิกใช้แล้ว

การใช้งานไม่ถูกต้องเมื่อทำงานกับการทำงานพร้อมกันหรือไม่

และถ้าฉันไม่ต้องการซิงโครไนซ์วัตถุด้วยตนเองและเพียงแค่ต้องการใช้คอลเลกชันเธรดที่ปลอดภัยโดยไม่จำเป็นต้องทำสำเนาใหม่ของอาเรย์ต้นแบบ (เช่นเดียวกับCopyOnWriteArrayList) มันจะใช้ได้Vectorไหม?

สิ่งที่เกี่ยวกับStackประเภทย่อยของVectorสิ่งที่ฉันควรใช้แทนมันได้หรือไม่


พวกเขาล้าสมัย แต่ไม่ได้คัดค้าน
มาร์ควิสแห่ง Lorne

คำตอบ:


655

Vectorประสานในการดำเนินงานของแต่ละบุคคล นั่นแทบไม่เคยเป็นสิ่งที่คุณต้องการจะทำ

โดยทั่วไปคุณต้องการซิงโครไนซ์ลำดับของการดำเนินการทั้งหมด การซิงโครไนซ์แต่ละการดำเนินการมีความปลอดภัยน้อยกว่า (ถ้าคุณวนซ้ำมากกว่า a Vectorคุณยังต้องทำการล็อกเพื่อหลีกเลี่ยงการเปลี่ยนคอลเลกชันในเวลาเดียวกันซึ่งจะทำให้เกิดConcurrentModificationExceptionการวนซ้ำในเธรด) แต่ก็ช้าลงด้วย เหตุใดจึงต้องปลดล็อคซ้ำ ๆ เมื่อหนึ่งครั้งจะเพียงพอ)

แน่นอนว่ามันยังมีค่าใช้จ่ายในการล็อคแม้ว่าคุณไม่จำเป็นต้อง

โดยทั่วไปมันเป็นวิธีการที่มีข้อบกพร่องอย่างมากในการซิงโครไนซ์ในสถานการณ์ส่วนใหญ่ ดังที่นาย Brian Henkชี้ให้เห็นคุณสามารถตกแต่งคอลเลกชันโดยใช้การเรียกเช่นCollections.synchronizedList- ความจริงที่Vectorรวมทั้งการปรับใช้คอลเลกชัน "ปรับขนาดอาร์เรย์" กับบิต "ซิงโครไนซ์ทุกการทำงาน" เป็นอีกตัวอย่างของการออกแบบที่ไม่ดี วิธีการตกแต่งช่วยให้แยกความกังวลได้ง่ายขึ้น

ในฐานะที่Stackเทียบเท่า - ฉันดูDeque/ ArrayDequeเริ่มต้นด้วย


108
"โดยทั่วไปคุณต้องการซิงโครไนซ์ลำดับการปฏิบัติทั้งหมด" - นั่นคือประเด็น! ขอบคุณ!
fjsj

7
ใน Java รุ่นที่คัดค้านเวกเตอร์ (ปัจจุบันฉันใช้ Java7). แต่ฉันไม่เคยเห็นว่าเลิกใช้แล้ว? บายคำอธิบายที่ดี ... + 1
Samir Mangroliya

17
@ ซามีร์: มันไม่ได้คัดค้านอย่างเป็นทางการ - เป็นเพียงแค่ ArrayList ที่ต้องการ
Jon Skeet

26
@ ซามีร์: ไม่ฉันจะไม่พยายามทำนายอนาคต
Jon Skeet

5
เพียงแค่ gr8 เวกเตอร์จะไม่เลิกของมรดก class.There ต้องมีความแตกต่างระหว่างเลิกและมรดกและใช่มีเห็นstackoverflow.com/questions/2873254/...
Prashant Shilimkar

82

Vector เป็นส่วนหนึ่งของ 1.0 - การใช้งานดั้งเดิมมีสองข้อเสีย:

1. การตั้งชื่อ:เว็กเตอร์เป็นเพียงรายการที่สามารถเข้าถึงได้ในรูปแบบอาร์เรย์ดังนั้นจึงควรถูกเรียกArrayList(ซึ่งเป็นการแทนที่คอลเลกชัน Java 1.2 สำหรับVector)

2. Concurrency:ทั้งหมดget(), set()วิธีการอยู่synchronizedดังนั้นคุณจึงไม่สามารถมีเม็ดเล็กปรับการควบคุมการทำข้อมูลให้ตรงกัน

ที่มีอยู่ไม่แตกต่างกันมากระหว่างArrayListและแต่คุณควรใช้VectorArrayList

จากเอกสาร API

ในฐานะที่เป็นแพลตฟอร์ม Java 2 v1.2 ชั้นนี้ได้รับการดัดแปลงเพื่อใช้อินเตอร์เฟซรายการทำให้มันเป็นสมาชิกของ Java Collections Framework ซึ่งแตกต่างจากการใช้คอลเลกชันใหม่ Vector ถูกทำข้อมูลให้ตรงกัน


รายการที่สามารถเข้าถึงได้เป็นอาร์เรย์? ArrayList ไม่ใช่ชื่อที่สั้นมากหรือเป็นที่จับใจซึ่งอาจเป็นสาเหตุที่ใช้เวกเตอร์ที่อื่น (เช่น STL)
dhardy

6
@dhardy List ที่มีอาร์เรย์เป็นการใช้งานพื้นฐาน มีArrayList, LinkedListฯลฯ ซึ่งทั้งหมดใช้อินเตอร์เฟซListดังนั้นหากคุณต้องการที่จะใช้Listวิธีการโดยไม่ต้องรู้ว่าสิ่งที่การดำเนินงานพื้นฐานเป็นจริงคุณก็สามารถใช้Listเป็นพารามิเตอร์กับวิธีการอื่น ๆ เช่นเดียวกับผู้พัฒนาของMapและอื่น ๆ ในขณะเดียวกัน C ++ มีstd::arrayคลาสซึ่งเป็นเพียงการแทนที่เทมเพลตสำหรับอาร์เรย์ความยาวคงที่แบบ C
JAB

41

นอกจากคำตอบที่ระบุไว้แล้วเกี่ยวกับการใช้ Vector เวกเตอร์ยังมีวิธีการมากมายเกี่ยวกับการแจงนับและการดึงองค์ประกอบที่แตกต่างจากรายการอินเตอร์เฟสและนักพัฒนา (โดยเฉพาะผู้ที่เรียนรู้ Java ก่อน 1.2) สามารถใช้พวกเขาได้ รหัส. แม้ว่าการแจกแจงจะเร็วกว่า แต่ก็ไม่ได้ตรวจสอบว่ามีการแก้ไขคอลเล็กชันในระหว่างการทำซ้ำซึ่งอาจทำให้เกิดปัญหาหรือไม่และเวกเตอร์อาจถูกเลือกสำหรับการทำข้อมูลให้ตรงกัน - ด้วยการเข้าถึงของผู้เข้าร่วมจากหลายเธรด การใช้วิธีการเหล่านี้ยังมีรหัสจำนวนมากสำหรับ Vector ซึ่งจะไม่ง่ายที่จะแทนที่ด้วยการใช้รายการที่แตกต่างกัน


14

คุณสามารถใช้synchronizedCollection / รายการวิธีการในการjava.util.Collectionที่จะได้รับชุดด้ายปลอดภัยจาก non-ด้ายปลอดภัยอย่างใดอย่างหนึ่ง


2
ทำไมจึงดีกว่าเวกเตอร์
fjsj

8
ดังที่ Jon กล่าวไว้ Vector จะทำงานได้ไม่ดีนักและวิธีนี้ช่วยให้คุณสามารถเลือกได้ว่าควรจะทำการซิงโครไนซ์เมื่อใด มันเป็นปัญหาการออกแบบโดยสิ้นเชิง คุณควรใช้ ArrayList ผ่าน Vector เพราะคุณควรใช้การเข้าถึงที่ไม่ซิงโครไนซ์
Brian Henk

คำถามนี้จะตอบคำถามได้อย่างไร
มาร์ควิสแห่ง Lorne

8

java.util.Stackสืบทอดค่าใช้จ่ายในการซิงโครไนซ์java.util.Vectorซึ่งมักจะไม่เป็นธรรม

แม้ว่าจะได้รับมรดกมากกว่านั้นมาก ความจริงที่ว่าjava.util.Stack extends java.util.Vectorเป็นความผิดพลาดในการออกแบบเชิงวัตถุ ครูสอนจะทราบว่ามันยังมีวิธีการมากมายนอกเหนือจากการดำเนินการแบบดั้งเดิมที่เกี่ยวข้องกับสแต็ค (เช่น: กด, ป๊อป, มอง, ขนาด) นอกจากนี้ยังเป็นไปได้ที่จะทำsearch, elementAt, setElementAt, removeและการดำเนินงาน random-access อื่น ๆ อีกมากมาย Stackมันเป็นพื้นขึ้นกับผู้ใช้ที่จะละเว้นจากการใช้การดำเนินงานที่ไม่ใช่สแต็คของ

สำหรับเหตุผลด้านประสิทธิภาพและการออกแบบ OOP เหล่านี้JavaDoc สำหรับการjava.util.StackแนะนำArrayDequeเป็นการทดแทนโดยธรรมชาติ (deque เป็นมากกว่าสแต็ก แต่อย่างน้อยก็ จำกัด ให้จัดการกับทั้งสองปลายแทนที่จะให้ทุกการเข้าถึงแบบสุ่ม)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.