
89. ArrayList แตกต่างจาก LinkedList อย่างไร
นี่เป็นหนึ่งในคำถามยอดนิยม พร้อมด้วยคำถามเกี่ยวกับโครงสร้างภายในของHashMap การสัมภาษณ์จะไม่สมบูรณ์หากไม่มีการสัมภาษณ์ ดังนั้นคำตอบของคุณควรหลุดออกจากปากทันที นอกจากสิ่งที่ชัดเจน (มีชื่อต่างกัน) แล้ว โครงสร้างภายในยังแตกต่างกันอีกด้วย ก่อนหน้านี้ เราได้พูดคุยถึงโครงสร้างภายในของทั้งArrayListและLinkedListดังนั้นฉันจะไม่เจาะลึกรายละเอียดการใช้งานของพวกเขา ฉันจะเตือนคุณว่าArrayListถูกนำมาใช้โดยใช้อาร์เรย์ภายในซึ่งขนาดจะเพิ่มขึ้นแบบไดนามิกตามสูตรนี้:<size of the current array> * 3 / 2 + 1
นอกจากนี้ การใช้งานLinkedListจะใช้รายการที่เชื่อมโยงแบบทวีคูณภายใน นั่นคือ แต่ละองค์ประกอบมีการอ้างอิงถึงองค์ประกอบก่อนหน้าและถัดไป ยกเว้นองค์ประกอบที่จุดเริ่มต้นและจุดสิ้นสุดของรายการ ผู้สัมภาษณ์ชอบถามคำถามแบบนี้ "อันไหนดีกว่ากันArrayListหรือLinkedList ?" หวังว่าจะจับคุณ ท้ายที่สุดแล้ว ถ้าคุณบอกว่าอย่างใดอย่างหนึ่งดีกว่า แสดงว่าคุณให้คำตอบที่ผิด 
-
หากไม่ได้ระบุดัชนี รายการใหม่จะถูกเพิ่มที่ส่วนท้ายของรายการทั้งสองประเภทโดยอัตโนมัติ ในLinkedListองค์ประกอบใหม่จะกลายเป็นส่วนท้ายใหม่ (มีเพียงการอ้างอิงคู่เดียวเท่านั้นที่จะถูกเขียนใหม่ ดังนั้นความซับซ้อนของอัลกอริทึมคือO(1) )
วิธีการเพิ่มจะเพิ่มองค์ประกอบลงในเซลล์ว่างสุดท้ายในอาร์เรย์ ( O(1) )
-
การเพิ่มรายการตามดัชนีมักจะหมายถึงการแทรกรายการนั้นไว้ตรงกลางรายการ ในLinkedListวิธีการจะค้นหาตำแหน่งที่ต้องการก่อนโดยวนซ้ำองค์ประกอบจากส่วนท้ายและส่วนหัว ( O(n/2) ) จากนั้นจะแทรกค่าโดยการเขียนทับการอ้างอิงขององค์ประกอบทั้งสองด้านของตำแหน่งที่ มีการแทรกองค์ประกอบใหม่ ( O(1) ) ความซับซ้อนของอัลกอริทึมโดยรวมของการดำเนินการนี้จะเป็นO(n/2 )
ในสถานการณ์เดียวกัน (เพิ่มด้วยดัชนี) ArrayListค้นหาตำแหน่งที่ต้องการ ( O(1) ) จากนั้นเลื่อนองค์ประกอบทั้งหมดที่อยู่ทางด้านขวา (รวมถึงองค์ประกอบที่เก็บไว้แล้วในดัชนีที่ระบุ) ไปทางขวาทีละรายการ (ซึ่ง อาจต้องมีการสร้างอาร์เรย์ภายในใหม่และคัดลอกองค์ประกอบไป) ( O(n/2) ) ความซับซ้อนโดยรวมคือO(n/2 )
-
การเพิ่มองค์ประกอบที่จุดเริ่มต้นของLinkedListนั้นคล้ายคลึงกับการเพิ่มองค์ประกอบที่ส่วนท้าย: องค์ประกอบใหม่จะกลายเป็นส่วนหัวใหม่ ( O(1) ) แต่สำหรับ ArrayList การดำเนินการนั้นจำเป็นต้องย้ายองค์ประกอบทั้งหมดไปทางขวา ( O(n) )
90. ArrayList แตกต่างจาก HashSet อย่างไร
หากเราสามารถเปรียบเทียบArrayListและLinkedListบนพื้นฐานการดำเนินงานโดยการดำเนินงานเพื่อพิจารณาว่าอันไหนดีกว่า เราจะพบว่าการเปรียบเทียบระหว่างArrayListและHashSet ไม่ใช่เรื่องง่ายนัก เนื่องจากเป็นคอลเลกชั่นที่แตกต่างกันโดยสิ้นเชิง คุณสามารถเปรียบเทียบของหวานกับอีกชิ้นหนึ่งได้ แต่การเปรียบเทียบของหวานกับอาหารจานคาวถือเป็นความท้าทาย เพราะพวกมันต่างกันอย่างเจ็บปวด อย่างไรก็ตาม ฉันจะพยายามชี้ให้เห็นความแตกต่างบางประการระหว่างพวกเขา:-
ArrayListใช้ อินเทอร์เฟซ รายการในขณะที่HashSetใช้อินเทอร์เฟซSet
-
ArrayListให้คุณเข้าถึงองค์ประกอบตามดัชนี: การดำเนินการ getมี ความซับซ้อนของอัลกอริทึม O(1)แต่HashSetให้คุณเข้าถึงองค์ประกอบที่ต้องการโดยการวนซ้ำเท่านั้น ซึ่งให้ผลลัพธ์ความซับซ้อนของอัลกอริทึมตั้งแต่O(1)ถึงO(n )
-
ArrayListอนุญาตให้มีองค์ประกอบที่ซ้ำกัน ในHashSetองค์ประกอบทั้งหมดจะไม่ซ้ำกัน: ความพยายามใด ๆ ที่จะเพิ่มองค์ประกอบที่มีอยู่แล้วในHashSetจะล้มเหลว (รายการที่ซ้ำกันจะถูกตรวจสอบโดย hashcode ดังนั้นชื่อของคอลเลกชันนี้)
-
ArrayListถูกนำไปใช้โดยใช้อาร์เรย์ภายใน แต่HashSetถูกนำไปใช้โดยใช้HashMapภายใน
-
ArrayListรักษาลำดับการแทรกขององค์ประกอบ แต่HashSetเป็นชุดที่ไม่เรียงลำดับและไม่รักษาลำดับขององค์ประกอบ
-
ArrayListอนุญาตให้มีค่า Null กี่ค่าก็ได้ แต่คุณสามารถเพิ่มค่า Null ให้กับHashSet ได้เพียงค่าเดียวเท่านั้น (ท้ายที่สุดแล้ว องค์ประกอบต่างๆ จะต้องไม่ซ้ำกัน)
91. เหตุใด Java จึงมีการใช้งานอาร์เรย์ไดนามิกที่แตกต่างกันมากมาย?
นี่เป็นคำถามเชิงปรัชญามากกว่า นอกจากนี้เรายังอาจถามว่าทำไมพวกเขาถึงมีเทคโนโลยีใหม่และหลากหลายมากมาย? เพื่อความสะดวก. และสิ่งเดียวกันนี้เป็นจริงเกี่ยวกับการใช้งานอาร์เรย์แบบไดนามิกจำนวนมาก ไม่มีสิ่งใดที่สามารถเรียกได้ว่าเป็นการนำไปใช้ที่ดีที่สุดหรือเหมาะสมที่สุด แต่ละสถานการณ์มีข้อดีเฉพาะของตัวเอง งานของเราคือการรู้ถึงความแตกต่างและจุดแข็ง/จุดอ่อนเพื่อให้สามารถใช้คอลเลกชันที่เหมาะสมที่สุดกับสถานการณ์ใดๆ ได้92. เหตุใด Java จึงมีการใช้งานหน่วยเก็บข้อมูลคีย์-ค่าที่แตกต่างกันมากมาย
ที่นี่สถานการณ์จะเหมือนกับการใช้งานอาร์เรย์แบบไดนามิก ไม่มีผู้ใดจะดีไปกว่าคนอื่นๆ ในระดับสากลอย่างแน่นอน แต่ละคนมีจุดแข็งและจุดอ่อน และแน่นอนว่าเราต้องใช้จุดแข็งของพวกเขาให้เกิดประโยชน์สูงสุด ตัวอย่าง:แพ็คเกจที่เกิดขึ้นพร้อมกันซึ่งมีคลาสแบบมัลติเธรดจำนวนมาก มีคอลเลกชันที่เกิดขึ้น พร้อมกันเป็นของตัวเอง คลาสConcurrentHashMapมีข้อได้เปรียบเหนือHashMap มาตรฐาน ในแง่ของความปลอดภัยเมื่อทำงานกับข้อมูลในสภาพแวดล้อมแบบมัลติเธรด แต่มาพร้อมกับประสิทธิภาพที่ช้าลง และการนำไปใช้งานที่ไม่ใช่ตัวเลือกที่ดีที่สุดในทุกสถานการณ์จะค่อยๆ เลิกใช้ไป ตัวอย่างเช่น: Hashtableซึ่งเดิมตั้งใจให้เป็นHashMap ที่ปลอดภัยสำหรับเธรด ถูกลืมและเลิกใช้งาน เนื่องจากConcurrentHashMapดีกว่าHashtableเมื่อทำงานในสภาพแวดล้อมแบบมัลติเธรด93. ฉันจะจัดเรียงคอลเลกชันขององค์ประกอบได้อย่างไร?
สิ่งแรกที่ต้องพูดคือคลาสที่แสดงถึงองค์ประกอบคอลเลกชันต้องใช้ อินเทอร์เฟซ ที่เปรียบเทียบได้ซึ่งประกอบด้วยเมธอดcomparisonTo หรือคุณต้องการคลาสที่ใช้ อินเทอร์เฟซ Comparatorรวมถึงวิธีการเปรียบเทียบ ด้วย ทั้งสองวิธีระบุวิธีเปรียบเทียบวัตถุประเภทที่กำหนด นี่เป็นสิ่งสำคัญเมื่อทำการเรียงลำดับ เนื่องจากอัลกอริธึมการเรียงลำดับจำเป็นต้องเข้าใจว่าจะใช้หลักการใดในการเปรียบเทียบองค์ประกอบ ส่วนใหญ่จะกระทำโดยการใช้Comparableโดยตรงในคลาสที่คุณต้องการเรียงลำดับ การใช้ตัวเปรียบเทียบนั้นพบได้น้อยกว่า สมมติว่าคุณกำลังใช้คลาสจากไลบรารีบางแห่งและไม่ได้ใช้งานComparableแต่คุณต้องเรียงลำดับคอลเลกชันของอ็อบเจ็กต์ เนื่องจากคุณไม่สามารถเปลี่ยนโค้ดของคลาสนี้ได้ (ยกเว้นโดยการขยาย) คุณจึงสามารถเขียนการใช้งานComparatorที่ระบุวิธีการเปรียบเทียบอ็อบเจ็กต์ของคลาสได้ และอีกตัวอย่างหนึ่ง หากคุณต้องการเรียงลำดับออบเจ็กต์ประเภทเดียวกันด้วยวิธีที่ต่างกัน คุณสามารถเขียน การใช้งาน Comparator หลายรายการ เพื่อใช้ในสถานการณ์ที่แตกต่างกันได้ ตามกฎแล้ว คลาสนอกกรอบจำนวนมาก เช่นStringได้ใช้อินเทอร์เฟซที่เปรียบเทียบได้ อยู่แล้ว นั่นหมายความว่าคุณไม่จำเป็นต้องกังวลเกี่ยวกับวิธีเปรียบเทียบคลาสเหล่านี้ คุณสามารถไปข้างหน้าและใช้มันได้ วิธี แรกและชัดเจนที่สุดคือการใช้คลาสTreeSetหรือTreeMap คลาสเหล่านี้จัดเก็บองค์ประกอบตามลำดับการจัดเรียงโดยอิงจากตัวเปรียบเทียบที่ดำเนินการโดยองค์ประกอบของคลาส อย่าลืมว่าTreeMapเรียงลำดับคีย์ ไม่ใช่ค่า หากคุณใช้ComparatorแทนComparableคุณจะต้องส่ง วัตถุ Comparatorไปยัง Constructor ของคอลเลกชันเมื่อคุณสร้างมันขึ้นมา:TreeSet treeSet = new TreeSet(customComparator);
แต่ถ้าคุณมีคอลเลกชันประเภทอื่นล่ะ? คุณจะเรียงลำดับมันอย่างไร? ในกรณีนี้ วิธี ที่สองของคลาสยูทิลิตี้Collections — วิธี sort() — มีความเหมาะสม วิธีการนี้เป็นแบบคงที่ ดังนั้นสิ่งที่คุณต้องทำก็แค่เติมชื่อของคลาสไว้หน้าแล้วส่งผ่านรายการที่จะเรียงลำดับ ตัวอย่างเช่น:
Collections.sort(someList);
หากคุณใช้ Comparator มากกว่า Comparable คุณจะต้องส่งผ่านเป็นอาร์กิวเมนต์ที่สอง:
Collections.sort(someList, customComparator);
การดำเนินการนี้จะเปลี่ยนลำดับภายในขององค์ประกอบในรายการที่ส่งผ่าน: รายการจะถูกจัดเรียงโดยใช้ตัวเปรียบเทียบ โปรดทราบว่ารายการที่ส่งผ่านจะต้องไม่แน่นอน มิฉะนั้นวิธีการจะล้มเหลวและโยนUnsupportedOperationException ตัวเลือก ที่สามคือการใช้ วิธี การเรียงลำดับของคลาสStreamซึ่งจะเรียงลำดับองค์ประกอบของคอลเลกชัน หากเราใช้Comparable :
someList = someList.stream().sorted().collect(Collectors.toList());
หากเราใช้Comparator :
someList = someList.stream().sorted(customComparator).collect(Collectors.toList());
วิธี ที่สี่คือการใช้อัลกอริธึมการเรียงลำดับด้วยตนเอง เช่นการเรียงลำดับแบบฟอง
หรือการเรียงลำดับแบบ
ผสาน
คลาสอ็อบเจ็กต์ เท่ากับ() และ hashCode()
94. ให้คำอธิบายโดยย่อเกี่ยวกับคลาส Object ใน Java
ในส่วนที่สอง ของการทบทวน เราได้กล่าวถึงวิธีการของคลาสObject แล้ว ที่นี่ฉันจะเตือนคุณว่า คลาส Objectเป็นบรรพบุรุษของทุกคลาสใน Java มี 11 วิธี ซึ่งสืบทอดมาจากทุกคลาสตามลำดับ
95. เท่ากับ() และ hashCode() ใช้ใน Java คืออะไร?
hashCode()เป็นวิธีการของ คลาส Objectที่สืบทอดมาจากทุกคลาส หน้าที่ของมันคือการสร้างตัวเลขที่แสดงถึงวัตถุเฉพาะ ตัวอย่างของวิธีการนี้ที่ใช้งานจริงสามารถพบได้ในHashMapโดยที่มันถูกเรียกบนออบเจ็กต์คีย์เพื่อรับแฮชโค้ดในเครื่อง ซึ่งจะกำหนดที่ฝากข้อมูล (เซลล์ของอาร์เรย์ภายใน) คู่คีย์-ค่าจะถูกจัดเก็บ นอกจากนี้ โดยทั่วไปวิธีนี้จะใช้ใน วิธี เท่ากับ ()ซึ่งเป็นหนึ่งในวิธีหลักในการระบุวัตถุ เท่ากับ()เป็นวิธีการของ คลาส Objectซึ่งมีหน้าที่ในการเปรียบเทียบวัตถุและพิจารณาว่าวัตถุนั้นเท่ากันหรือไม่ วิธีการนี้ใช้ในทุกที่ที่เราต้องการเปรียบเทียบวัตถุ เนื่องจาก ตัวดำเนินการเปรียบเทียบ == มาตรฐาน ไม่เหมาะสำหรับวัตถุ เนื่องจากจะเปรียบเทียบเฉพาะการอ้างอิงวัตถุเท่านั้น96. บอกเราเกี่ยวกับสัญญาระหว่างเท่ากับ() และ hashCode() ใน Java?
ก่อนอื่น ให้ฉันบอกว่าเพื่อให้เมธอดเท่ากับ()และhashCode()ทำงานได้อย่างถูกต้อง จะต้องเขียนทับอย่างถูกต้อง การใช้งานใหม่ต้องเป็นไปตามกฎเหล่านี้:- ออบเจ็กต์ที่ เหมือนกันซึ่งคืนค่าเป็นจริง จะต้องมีรหัสแฮชเดียวกัน
- วัตถุที่มีรหัสแฮชเดียวกันไม่จำเป็นต้องเท่ากัน
GO TO FULL VERSION