จุดเริ่มต้นของเส้นทาง
วันนี้ฉันอยากจะพูดถึงหัวข้อที่น่าสนใจเช่น “
Java Collections Framework ” หรือพูดง่ายๆ ก็คือเกี่ยวกับคอลเลกชั่น งานของโค้ดส่วนใหญ่กำลังประมวลผลข้อมูลในรูปแบบใดรูปแบบหนึ่ง รับรายชื่อผู้ใช้ รับรายชื่อที่อยู่ ฯลฯ เรียงลำดับ ทำการค้นหา เปรียบเทียบ นี่คือเหตุผลว่าทำไมความรู้เรื่องการสะสมจึงถือเป็นทักษะหลัก นั่นเป็นเหตุผลที่ฉันอยากจะพูดคุยเกี่ยวกับเรื่องนี้ นอกจากนี้ หนึ่งในคำถามที่พบบ่อยที่สุดในการสัมภาษณ์นักพัฒนา Java ก็คือคอลเล็กชัน ตัวอย่างเช่น "วาดลำดับชั้นของคอลเลกชัน" คอมไพเลอร์ออนไลน์จะช่วยเราในการเดินทาง ตัวอย่างเช่น คุณสามารถใช้ " Tutorialspoint
Online Java Compiler " หรือ
Repl.it เส้นทางสู่การทำความรู้จักกับโครงสร้างข้อมูลใดๆ เริ่มต้นด้วยตัวแปรธรรมดา (ตัวแปร) บนเว็บไซต์ของ Oracle หัวข้อต่างๆ จะแสดงเป็น "เส้นทาง" หรือเส้นทาง ดังนั้นเส้นทางสู่การทำความรู้จักกับ Java จึงเรียกว่า “
Trail: Learning the Java Language: Table of Contents ” และพื้นฐานของภาษา (เช่น พื้นฐานภาษา) เริ่มต้นด้วยตัวแปร ดังนั้นเรามาเขียนโค้ดง่ายๆ:
public static void main(String[] args) {
String user = "Max";
System.out.println("Hello, " + user);
}
เป็นสิ่งที่ดีในทุกสิ่ง ยกเว้นว่าเราเข้าใจว่าโค้ดนี้ดีและสวยงามสำหรับตัวแปรตัวเดียวเท่านั้น จะทำอย่างไรถ้ามีหลายอัน? อาร์เรย์ถูกประดิษฐ์ขึ้นเพื่อจัดเก็บข้อมูลประเภทเดียว ใน Trail เดียวกันจาก Oracle มีส่วนแยกต่างหากสำหรับอาร์เรย์โดยเฉพาะ ส่วนนี้เรียกว่า: "
อาร์เรย์ " การทำงานกับอาร์เรย์ก็ค่อนข้างง่าย:
import java.util.Arrays;
class Main {
public static void main(String[] args) {
String[] users = new String[2];
users[0] = "Max";
users[1] = "John";
System.out.println("Hello, " + Arrays.toString(users));
}
}
อาร์เรย์แก้ปัญหาการจัดเก็บค่าหลายค่าไว้ในที่เดียว แต่มันมีข้อจำกัด: ขนาดอาเรย์คงที่ ดังตัวอย่าง หากเราบอกว่าขนาด = 2 ก็จะเท่ากับ 2 นั่นคือทั้งหมดที่ หากเราต้องการอาร์เรย์ที่ใหญ่ขึ้น เราจำเป็นต้องสร้างอินสแตนซ์ใหม่ นอกจากนี้ การค้นหาองค์ประกอบก็เป็นเรื่องยากสำหรับอาร์เรย์เช่นกัน มีวิธีหนึ่ง
Arrays.binarySearch
แต่การค้นหานี้ใช้ได้กับอาร์เรย์ที่เรียงลำดับแล้วเท่านั้น (สำหรับอาร์เรย์ที่ไม่ได้เรียงลำดับ ผลลัพธ์จะไม่ได้กำหนดไว้หรือคาดเดาไม่ได้) นั่นคือการค้นหาจะทำให้เราต้องเรียงลำดับในแต่ละครั้ง การลบจะเป็นการล้างค่าเท่านั้น ดังนั้นเราจึงยังไม่ทราบว่าจริงๆ แล้วมีข้อมูลอยู่ในอาร์เรย์จำนวนเท่าใด เรารู้เพียงจำนวนเซลล์ในอาร์เรย์เท่านั้น หากต้องการรีเฟรชความรู้เกี่ยวกับอาร์เรย์:
และจากการพัฒนาภาษา Java ทำให้ Java Collections Framework ปรากฏใน JDK 1.2 ซึ่งเราจะพูดถึงในวันนี้
ของสะสม
เริ่มคิดต้นทุนตั้งแต่เริ่มต้น ทำไมต้องเป็นคอลเลกชัน? คำนี้มาจากสิ่งต่างๆ เช่น "ทฤษฎีประเภท" และ "ประเภทข้อมูลนามธรรม" แต่ถ้าคุณไม่มองเรื่องสูงๆ เลย เมื่อเรามีหลายสิ่งก็เรียกได้ว่าเป็น “ของสะสม” พวกที่สะสมของ. โดยทั่วไปคำว่า collect มาจากภาษาละติน collectio "การรวบรวมการรวบรวม" นั่นคือคอลเลกชั่นคือคอลเลกชั่นของบางสิ่งบางอย่าง ซึ่งเป็นคอนเทนเนอร์สำหรับองค์ประกอบบางอย่าง ดังนั้นเราจึงมีองค์ประกอบต่างๆ เราอาจต้องการทำอะไรกับมัน:
อย่างที่คุณเห็น เราอาจต้องการสิ่งที่ค่อนข้างสมเหตุสมผล เรายังเข้าใจด้วยว่าเราอาจต้องการทำอะไรบางอย่างกับหลายคอลเลกชัน:
ดังนั้น นักพัฒนา Java จึงเขียนอินเท อ ร์เฟซ
java.util.Collectionเพื่ออธิบายลักษณะการทำงานทั่วไปนี้สำหรับคอลเลกชันทั้งหมด อินเทอร์เฟซคอลเลกชันเป็นที่ที่คอลเลกชันทั้งหมดเกิดขึ้น คอลเลกชันคือแนวคิด มันเป็นแนวคิดว่าคอลเลกชันทั้งหมดควรประพฤติตนอย่างไร ดังนั้นคำว่า "คอลเลกชัน" จึงแสดงเป็นอินเทอร์เฟซ แน่นอนว่าอินเทอร์เฟซจำเป็นต้องมีการใช้งาน อินเทอร์เฟ
java.util.Collection
ซมีคลาสนามธรรม
AbstractCollection
นั่นคือ "คอลเลกชันนามธรรม" บางส่วน ซึ่งแสดงถึงโครงกระดูกสำหรับการใช้งานอื่นๆ (ตามที่เขียนใน JavaDoc เหนือคลาส
java.util.AbstractCollection
) เมื่อพูดถึงคอลเลกชั่น เราย้อนกลับไปและจำไว้ว่าเราต้องการจะย้ำคอลเลกชั่นเหล่านั้น ซึ่งหมายความว่าเราต้องการวนซ้ำองค์ประกอบต่างๆ ทีละรายการ นี่เป็นแนวคิดที่สำคัญมาก ดังนั้นอินเทอร์เฟซ
Collection
จึงสืบทอดมาจาก
Iterable
. สิ่งนี้สำคัญมากเพราะว่า... ประการแรก ทุกสิ่งที่ Iterable จะต้องสามารถส่งคืน Iterator ตามเนื้อหาได้ และประการที่สอง ทุกอย่างที่ Iterable สามารถนำไปใช้ในลูป
for-each-loop
ได้ และด้วยความช่วยเหลือของตัววนซ้ำ ที่จะ นำวิธี
AbstractCollection
การต่างๆ เช่น
contains
, มาใช้ และเส้นทางสู่การทำความเข้าใจคอลเลกชันเริ่มต้นด้วยหนึ่งในโครงสร้างข้อมูลที่พบบ่อยที่สุด - รายการเช่น .
toArray
remove
List
รายการ
ดังนั้นรายการจึงมีความสำคัญในลำดับชั้นของคอลเลกชัน:
ดังที่เราเห็น รายการใช้ อินเท อ ร์เฟซ
java.util.List รายการแสดงว่าเรามีคอลเลกชันขององค์ประกอบที่จัดเรียงตามลำดับบางอย่าง แต่ละองค์ประกอบมีดัชนี (เหมือนในอาร์เรย์) โดยปกติแล้ว รายการจะทำให้คุณมีองค์ประกอบที่มีค่าเท่ากันได้ ดังที่เราได้กล่าวไว้ข้างต้น
List
มันรู้เกี่ยวกับดัชนีขององค์ประกอบ สิ่งนี้ช่วยให้คุณได้รับ (
get
) องค์ประกอบตามดัชนีหรือตั้งค่าสำหรับดัชนีเฉพาะ (
set
) วิธีการรวบรวม
add
, ช่วย
addAll
ให้
remove
คุณสามารถระบุดัชนีที่จะดำเนินการได้ นอกจากนี้ y
List
ยังมีตัววนซ้ำเวอร์ชันของตัวเองที่เรียกว่า
ListIterator
. ตัววนซ้ำนี้รู้เกี่ยวกับดัชนีขององค์ประกอบ ดังนั้นจึงสามารถวนซ้ำได้ไม่เพียงแต่ไปข้างหน้าเท่านั้น แต่ยังย้อนกลับได้อีกด้วย สามารถสร้างได้จากสถานที่เฉพาะในคอลเลกชันด้วยซ้ำ ในบรรดาการใช้งานทั้งหมด มีสองประเภทที่ใช้บ่อยที่สุด:
ArrayList
และ
LinkedList
. อันดับแรก
ArrayList
คือรายการ (
List
) ตามอาร์เรย์ (
Array
) สิ่งนี้ช่วยให้คุณบรรลุ "การเข้าถึงแบบสุ่ม"
ไปยังองค์ประกอบต่างๆ การเข้าถึงแบบสุ่มคือความสามารถในการดึงข้อมูลองค์ประกอบตามดัชนีทันที แทนที่จะวนซ้ำองค์ประกอบทั้งหมดจนกว่าเราจะพบองค์ประกอบที่มีดัชนีที่ต้องการ มันเป็นอาร์เรย์ที่เป็นพื้นฐานที่ช่วยให้บรรลุสิ่งนี้ได้ ในทางตรงกันข้าม
LinkedList
มันเป็นรายการที่เชื่อมโยง แต่ละรายการในรายการที่เชื่อมโยงจะแสดงในรูปแบบ
Entry
ซึ่งจัดเก็บข้อมูลเอง เช่นเดียวกับลิงก์ไปยังรายการถัดไป (ถัดไป) และก่อนหน้า (ก่อนหน้า
Entry
) จึง ใช้ "
LinkedList
Sequential Access
" เป็นที่ชัดเจนว่าในการหาองค์ประกอบที่ 5 เราจะต้องไปจากองค์ประกอบแรกไปยังองค์ประกอบสุดท้ายเพราะว่า เราไม่สามารถเข้าถึงองค์ประกอบที่ห้าได้โดยตรง เราสามารถเข้าถึงได้จากองค์ประกอบที่ 4 เท่านั้น ความแตกต่างในแนวคิดมีดังต่อไปนี้:
ในการทำงานอย่างที่คุณเข้าใจก็มีความแตกต่างเช่นกัน เช่น การเพิ่มองค์ประกอบ องค์ประกอบ
LinkedList
ต่างๆ เชื่อมต่อกันเหมือนเป็นลิงก์ในลูกโซ่ แต่
ArrayList
จะเก็บองค์ประกอบไว้ในอาร์เรย์ และอย่างที่เรารู้กันว่าอาร์เรย์ไม่สามารถเปลี่ยนขนาดของมันได้ แล้วมันทำงานยังไงล่ะ
ArrayList
? และมันก็ใช้งานได้ง่ายมาก เมื่อพื้นที่ในอาเรย์หมด พื้นที่จะเพิ่มขึ้น 1.5 เท่า นี่คือรหัสการซูม:
int newCapacity = oldCapacity + (oldCapacity >> 1);
ความแตกต่างในการทำงานอีกประการหนึ่งคือการแทนที่องค์ประกอบต่างๆ เช่นเมื่อเพิ่มหรือลบองค์ประกอบที่อยู่ตรงกลาง หากต้องการลบออกจาก
LinkedList
องค์ประกอบ เพียงลบการอ้างอิงไปยังองค์ประกอบนี้ ในกรณีของเรา
ArrayList
ถูกบังคับให้เปลี่ยนองค์ประกอบในแต่ละครั้งโดยใช้
System.arraycopy
ดังนั้นยิ่งมีองค์ประกอบมากเท่าไรก็ยิ่งต้องดำเนินการมากขึ้นเท่านั้น คำอธิบายโดยละเอียดเพิ่มเติมสามารถพบได้ในบทความเหล่านี้:
เมื่อตรวจสอบ ArrayList แล้ว ก็อดไม่ได้ที่จะจำคลาส
java.util.Vector ซึ่งเป็นคลาส "รุ่นก่อน" ได้ มันแตกต่างตรง
Vector
ที่
ArrayList
วิธีการทำงานกับคอลเลกชัน (การเพิ่ม, การลบ, ฯลฯ ) จะถูกซิงโครไนซ์ นั่นคือ หากเธรดหนึ่ง (
Thread
) เพิ่มองค์ประกอบ เธรดอื่นๆ จะรอจนกว่าเธรดแรกจะทำงานเสร็จ เนื่องจากมักไม่ต้องการความปลอดภัยของเธรด จึงแนะนำให้ใช้คลาสในกรณีดังกล่าว ดังที่ระบุไว้อย่างชัดเจนใน JavaDoc สำหรับ
ArrayList
คลาส
Vector
นอกจากนี้
Vector
ยังเพิ่มขนาดไม่ 1.5 เท่า
ArrayList
แต่เพิ่มขึ้น 2 เท่า มิฉะนั้นพฤติกรรมจะเหมือนกัน -
Vector
การจัดเก็บองค์ประกอบในรูปแบบของอาร์เรย์จะถูกซ่อนไว้ และการเพิ่ม/ลบองค์ประกอบจะมีผลเช่นเดียวกับ
ArrayList
ใน อันที่จริง
Vector
เราจำสิ่งนี้ได้ด้วยเหตุผล หากเราดูใน Javadoc เราจะเห็นโครงสร้างเช่น
java.util.Stack ใน "Direct Known Subclasses " Stack เป็นโครงสร้างที่น่าสนใจที่เป็น
last-in-first-out
โครงสร้าง LIFO (เข้าหลังออกก่อน) Stack ที่แปลจากภาษาอังกฤษคือ Stack (เช่น กองหนังสือ เป็นต้น) สแต็กใช้วิธีการเพิ่มเติม:
peek
(look, look),
pop
(push),
push
(push) วิธีการนี้
peek
แปลได้ว่า look (เช่น
มองเข้าไปในกระเป๋าแปลว่า “
มองเข้าไปในกระเป๋า ” และ
การมองผ่านรูกุญแจแปลว่า “
มองผ่านรูกุญแจ ”) วิธีนี้ช่วยให้คุณดูที่ "ด้านบน" ของสแต็กได้ เช่น รับองค์ประกอบสุดท้ายโดยไม่ต้องลบ (เช่นโดยไม่ต้องลบ) ออกจากสแต็ก วิธีการ
push
ผลัก (เพิ่ม) องค์ประกอบใหม่ลงบนสแต็กและส่งกลับ และวิธีการองค์ประกอบ
pop
จะผลัก (ลบ) และส่งคืนองค์ประกอบที่ถูกลบออก ในทั้งสามกรณี (เช่น peek, pop และ push) เราจะทำงานกับองค์ประกอบสุดท้ายเท่านั้น (เช่น "ด้านบนของสแต็ก") นี่คือคุณสมบัติหลักของโครงสร้างสแต็ก อย่างไรก็ตาม มีงานที่น่าสนใจในการทำความเข้าใจสแต็กตามที่อธิบายไว้ในหนังสือ “A Programmer's Career” (Cracking Coding Interview) มีงานที่น่าสนใจที่ต้องใช้โครงสร้าง “สแต็ก” (LIFO) คุณต้องใช้ “คิว” ” โครงสร้าง (FIFO) มันควรมีลักษณะเช่นนี้:
การวิเคราะห์งานนี้สามารถพบได้ที่นี่: "
ใช้งานคิวโดยใช้สแต็ก - The Queue ADT ("ใช้งานคิวโดยใช้สแต็ค" บน LeetCode) " ดังนั้นเราจึงย้ายไปยังโครงสร้างข้อมูลใหม่อย่างราบรื่น - คิว
คิว
คิวเป็นโครงสร้างที่เราคุ้นเคยมาตลอดชีวิต ต่อคิวไปร้านค้าไปหาหมอ ใครมาก่อน (First In) จะเป็นคนแรกที่ออกจากคิว (First Out) ใน Java คิวจะถูกแสดงโดย อินเตอร์เฟส
java.util.Queue ตาม Javadoc ของคิว คิวจะเพิ่มเมธอดต่อไปนี้:
อย่างที่คุณเห็นมีวิธีการสั่งซื้อ (ความล้มเหลวในการดำเนินการนั้นเต็มไปด้วยข้อยกเว้น) และมีวิธีคำขอ (การไม่สามารถดำเนินการได้ไม่ทำให้เกิดข้อผิดพลาด) นอกจากนี้ยังสามารถรับองค์ประกอบได้โดยไม่ต้องลบออก (ดูหรือองค์ประกอบ) อิน เทอร์เฟซคิวยังมีตัวตายตัวแทนที่มีประโยชน์ -
Deque นี่คือสิ่งที่เรียกว่า "คิวสองทาง" นั่นคือคิวดังกล่าวช่วยให้คุณใช้โครงสร้างนี้ทั้งจากจุดเริ่มต้นและจุดสิ้นสุด เอกสารระบุว่า "Deques ยังสามารถใช้เป็นสแต็ก LIFO (เข้าก่อน-ออกก่อน) ได้ อินเทอร์เฟซนี้ควรใช้ในการตั้งค่าตามความชอบของคลาส Stack ดั้งเดิม" นั่นคือ ขอแนะนำให้ใช้การใช้งาน Deque แทน ซ้อนกัน. Javadoc แสดงวิธีการที่อินเทอร์เฟซ Deque อธิบาย:
มาดูกันว่ามีการใช้งานอะไรบ้าง และเรา จะเห็นข้อเท็จจริงที่น่าสนใจ - LinkedList ได้เข้าสู่ค่ายคิวแล้ว) นั่นคือ LinkedList ดำเนินการทั้ง
List
และ
Deque
แต่ก็มี “คิวเท่านั้น” เช่นกัน
PriorityQueue
เช่น เธอไม่ได้ถูกจดจำบ่อยนัก แต่ไร้ประโยชน์ ประการแรก คุณไม่สามารถใช้ "วัตถุที่ไม่สามารถเปรียบเทียบได้" ในคิวนี้ได้ เช่น ต้องระบุตัวเปรียบเทียบอย่างใดอย่างหนึ่งหรือวัตถุทั้งหมดจะต้องเปรียบเทียบได้ ประการที่สอง "การใช้งานนี้ให้เวลา O(log(n)) สำหรับวิธีการจัดคิวและการจัดคิว" ความซับซ้อนของลอการิทึมมีเหตุผลอยู่ ใช้งาน PriorityQueue ตามฮีป Javadoc กล่าวว่า: "คิวลำดับความสำคัญแสดงเป็นฮีปไบนารีที่สมดุล" ที่เก็บข้อมูลสำหรับสิ่งนี้คืออาเรย์ปกติ ซึ่งเติบโตเมื่อมีความจำเป็น เมื่อฮีปมีขนาดเล็กก็จะเพิ่มขึ้น 2 เท่า แล้วอีก 50% ความคิดเห็นจากรหัส: "เพิ่มเป็นสองเท่าหากเล็ก มิฉะนั้นจะเติบโต 50%" คิวลำดับความสำคัญและ Binary Heap เป็นหัวข้อที่แยกจากกัน หากต้องการข้อมูลเพิ่มเติม:
การใช้งานอาจ
java.util.Deque
เป็น คลาส
java.util.ArrayDeque นั่นคือ รายการสามารถนำไปใช้ได้โดยใช้รายการที่เชื่อมโยงและอาร์เรย์ และคิวยังสามารถนำไปใช้ได้โดยใช้อาร์เรย์หรือใช้รายการที่เชื่อมโยง
Queue
และอินเทอร์เฟซ มีการสืบทอดที่แสดง ถึง
Deque
"คิวการบล็อก":
BlockingQueue
และ
BlockingDeque
นี่คือการเปลี่ยนแปลงอินเทอร์เฟซเมื่อเทียบกับคิวปกติ:
มาดูตัวอย่างการบล็อกคิวกัน แต่พวกเขามีความน่าสนใจ ตัวอย่างเช่น BlockingQueue ถูกนำมาใช้โดย:
PriorityBlockingQueue ,
SynchronousQueue , ArrayBlockingQueue ,
DelayQueue ,
LinkedBlockingQueue แต่ พวกเขาใช้ทุกอย่างจาก Collection Frameworks
BlockingDeque
มาตรฐาน
LinkedBlockingDeque
แต่ละคิวเป็นหัวข้อรีวิวแยกกัน และภายในกรอบของการทบทวนนี้ เราจะพรรณนาถึงลำดับชั้นของคลาสไม่เพียงแต่ด้วย
List
แต่ยังรวมถึง
Queue
:
ดังที่เราเห็นจากแผนภาพ อินเทอร์เฟซและคลาสของ Java Collections Framework มีความเชื่อมโยงกันอย่างมาก มาเพิ่มอีกสาขาหนึ่งของลำดับชั้น -
Set
.
ชุด
Set
— แปลว่า “ชุด” มันแตกต่าง จากคิวและรายการ
Set
ในแง่นามธรรมมากกว่าการจัดเก็บองค์ประกอบ
Set
- เหมือนถุงใส่สิ่งของ โดยไม่รู้ว่าวัตถุนั้นตั้งอยู่อย่างไร และวางอยู่ในลำดับใด ใน Java ชุดดังกล่าวจะแสดงโดย อินเท อ ร์เฟ
ซ java.util.Set ตามที่เอกสารระบุไว้
Set
นี่คือ "คอลเลกชันที่ไม่มีองค์ประกอบที่ซ้ำกัน" ที่น่าสนใจคืออินเทอร์เฟซนั้น
Set
ไม่ได้เพิ่มวิธีการใหม่ให้กับอินเทอร์เฟซ
Collection
แต่เพียงชี้แจงข้อกำหนดเท่านั้น (เกี่ยวกับสิ่งที่ไม่ควรมีรายการที่ซ้ำกัน) นอกจากนี้ จากคำอธิบายก่อนหน้านี้ ระบุว่าคุณไม่สามารถ
Set
รับองค์ประกอบจากองค์ประกอบนั้น ได้ Iterator ใช้เพื่อรับองค์ประกอบ
Set
มีอินเทอร์เฟซเพิ่มเติมอีกหลายรายการที่เกี่ยวข้องกัน อันแรกก็คือ
SortedSet
. ตามชื่อที่แนะนำ
SortedSet
บ่งชี้ว่าชุดดังกล่าวถูกจัดเรียง ดังนั้นองค์ประกอบจึงใช้อินเทอร์เฟซหรือ
Comparable
ระบุ
Comparator
นอกจากนี้ยัง
SortedSet
มีวิธีการที่น่าสนใจหลายประการ:
นอกจากนี้ยังมีวิธีการ
first
(องค์ประกอบที่เล็กที่สุดตามค่า) และ
last
(องค์ประกอบที่ใหญ่ที่สุดตามค่า) มี
SortedSet
ทายาท -
NavigableSet
. วัตถุประสงค์ของอินเทอร์เฟซนี้คือการอธิบายวิธีการนำทางที่จำเป็นเพื่อระบุองค์ประกอบที่เหมาะสมได้แม่นยำยิ่งขึ้น สิ่งที่น่าสนใจคือ
NavigableSet
มันเพิ่มตัววนซ้ำตามปกติ (ซึ่งเปลี่ยนจากเล็กที่สุดไปใหญ่ที่สุด) ตัววนซ้ำสำหรับลำดับย้อนกลับ
descendingIterator
- นอกจากนี้ยัง
NavigableSet
ช่วยให้คุณใช้วิธี
descendingSet
รับมุมมองของตัวเอง (View) ซึ่งองค์ประกอบต่างๆ อยู่ในลำดับย้อนกลับ สิ่งนี้ถูกเรียก
View
เพราะว่าคุณสามารถเปลี่ยนองค์ประกอบขององค์ประกอบดั้งเดิมผ่านองค์ประกอบผลลัพธ์
Set
ได้ โดยพื้นฐานแล้วมันคือการนำเสนอข้อมูลต้นฉบับในรูปแบบที่แตกต่างออกไป ไม่ใช่สำเนาของข้อมูลดังกล่าว สิ่งที่น่าสนใจ
NavigableSet
เช่น
Queue
สามารถจัดการองค์ประกอบ
pollFirst
(น้อยที่สุด) และ (สูงสุด) ได้
pollLast
นั่นคือได้รับองค์ประกอบนี้และลบออกจากชุด มีการใช้งานประเภทใดบ้าง? ประการแรก การใช้งานที่มีชื่อเสียงที่สุดนั้นใช้รหัสแฮช -
HashSet การใช้งานที่รู้จักกันดีไม่แพ้กันอีกอย่าง หนึ่งนั้นใช้ต้นไม้สีแดงดำ -
TreeSet มาทำแผนภาพของเราให้สมบูรณ์:
ภายในคอลเลกชันยังคงต้องแยกแยะลำดับชั้น - ฤาษี ซึ่งเมื่อมองแวบแรกก็ยืนเคียงข้างกัน -
java.util.Map
.
แผนที่
แผนที่เป็นโครงสร้างข้อมูลที่จัดเก็บข้อมูลด้วยคีย์ ตัวอย่างเช่น กุญแจอาจเป็นรหัสหรือรหัสเมือง และด้วยคีย์นี้เองที่ข้อมูลจะถูกค้นหา ที่น่าสนใจคือการ์ดจะแสดงแยกกัน ตามที่นักพัฒนา (ดู "
คำถามที่พบบ่อยเกี่ยวกับการออกแบบ Java Collections API ") การแมปคีย์-ค่าไม่ใช่คอลเลกชัน และแผนที่สามารถถูกมองว่าเป็นชุดของคีย์ ชุดของค่า ชุดของคู่ของคีย์-ค่าได้รวดเร็วยิ่งขึ้น นี่เป็นสัตว์ที่น่าสนใจมาก การ์ดมีวิธีการใดบ้าง? ลองดูที่อินเทอร์เฟซ Java API
java.util.Map เพราะ เนื่องจากแผนที่ไม่ใช่คอลเล็กชัน (ไม่ได้รับการสืบทอดจากคอลเล็กชัน) จึงไม่มีไฟล์
contains
. และนี่คือตรรกะ แผนที่ประกอบด้วยคีย์และค่า วิธีใดต่อไปนี้ควรตรวจสอบ
contains
และทำอย่างไรไม่ให้สับสน? ดังนั้นอินเทอร์เฟซจึง
Map
มีสองเวอร์ชันที่แตกต่างกัน:
containsKey
(ประกอบด้วยคีย์) และ
containsValue
(ประกอบด้วยค่า) การใช้มัน
keySet
ช่วยให้คุณได้รับชุดกุญแจ (อันเดียวกัน
Set
) และการใช้วิธีการนี้
values
ทำให้เราสามารถรวบรวมค่าต่างๆ ในแผนที่ได้ ปุ่มต่างๆ ในแผนที่มีเอกลักษณ์เฉพาะตัว ซึ่งเน้นที่โครงสร้าง
Set
ข้อมูล สามารถทำซ้ำค่าได้ซึ่งเน้นโดยโครงสร้างข้อมูล Collection นอกจากนี้ เมื่อใช้วิธีนี้
entrySet
เราสามารถรับชุดคู่คีย์-ค่าได้ คุณสามารถอ่านเพิ่มเติมเกี่ยวกับการใช้งานการ์ดได้ในการวิเคราะห์โดยละเอียดที่สุด:
ฉันยังต้องการที่จะเห็นสิ่งที่คล้าย
HashMap
กับ
HashSet
และ
TreeMap
ถึง
TreeSet
พวกเขายังมีอินเทอร์เฟซที่คล้ายกัน:
NavigableSet
ทั้ง
NavigableMap
สอง
SortedSet
และ
SortedMap
. ดังนั้นแผนที่สุดท้ายของเราจะมีลักษณะดังนี้:
เราขอจบด้วยข้อเท็จจริงที่น่าสนใจที่คอลเลกชัน
Set
ใช้ภายใน
Map
โดยที่ค่าที่เพิ่มคือคีย์ และค่าจะเหมือนกันทุกที่ สิ่งนี้น่าสนใจเพราะ
Map
ไม่ใช่การรวบรวมและการคืนสินค้า
Set
ซึ่งเป็นการรวบรวม แต่ในความเป็นจริงแล้วถูกนำไปใช้
Map
เป็น เหนือจริงเล็กน้อย แต่นั่นคือสิ่งที่เกิดขึ้น)
บทสรุป
ข่าวดีก็คือว่าการรีวิวนี้สิ้นสุดที่นี่ ข่าวร้ายก็คือว่านี่เป็นบทความที่มีการวิจารณ์มาก การใช้งานแต่ละคอลเลกชันควรได้รับบทความแยกต่างหาก และสำหรับแต่ละอัลกอริทึมที่ซ่อนอยู่จากสายตาของเรา แต่จุดประสงค์ของการตรวจสอบนี้คือเพื่อจดจำว่ามันคืออะไรและมีความเชื่อมโยงระหว่างอินเทอร์เฟซอย่างไร ฉันหวังว่าหลังจากอ่านอย่างถี่ถ้วนแล้ว คุณจะสามารถวาดไดอะแกรมของคอลเลกชันจากหน่วยความจำได้
ตามปกติแล้วบางลิงค์:
#เวียเชสลาฟ
GO TO FULL VERSION