สวัสดี! วันนี้เราจะพูดถึงโครงสร้างข้อมูลอื่น - แผนที่ ชื่ออย่างเป็นทางการของรัสเซียคือ "อาเรย์แบบเชื่อมโยง" แต่ไม่ได้ใช้บ่อยนัก ตัวเลือกทั่วไปคือ "พจนานุกรม", "แผนที่" หรือ (บ่อยที่สุด) ภาษาอังกฤษแบบสแลง "แผนที่" :) ภายในแผนที่ข้อมูลจะถูกจัดเก็บในรูปแบบ "คีย์" - "ค่า" นั่นคือเป็นคู่ ทั้งคีย์และค่าสามารถเป็นอ็อบเจ็กต์ใดก็ได้ เช่น ตัวเลข สตริง หรืออ็อบเจ็กต์ของคลาสอื่น
Map แตกต่างจากโครงสร้างข้อมูลอื่นๆ อย่างไร
ก่อนหน้านี้ เราพิจารณาโครงสร้างข้อมูลที่องค์ประกอบต่างๆ ถูกจัดเก็บด้วยตัวเอง ในอาร์เรย์หรือArrayList / LinkedListเราจัดเก็บองค์ประกอบจำนวนหนึ่ง แต่จะเกิดอะไรขึ้นถ้างานของเราเปลี่ยนแปลงเล็กน้อย? ตัวอย่างเช่น ลองนึกภาพว่าเรากำลังเผชิญกับภารกิจสร้างรายชื่อ 100 คน โดยจะเก็บชื่อนามสกุลและหมายเลขหนังสือเดินทางของบุคคลนั้นไว้ โดยหลักการแล้วมันไม่ยากขนาดนั้น ตัวอย่างเช่น คุณสามารถใส่ทั้งสองบรรทัดและสร้างรายการบรรทัดได้ดังนี้: “Anna Ivanovna Reshetnikova, 4211 717171” แต่โซลูชันนี้มีข้อเสียสองประการ ขั้นแรกเราอาจต้องมีฟังก์ชั่นค้นหาหนังสือเดินทาง และด้วยรูปแบบการจัดเก็บข้อมูลแบบนี้ก็จะเกิดปัญหา และประการที่สอง ไม่มีอะไรจะขัดขวางเราจากการสร้างคนสองคนที่มีหมายเลขหนังสือเดินทางเดียวกันได้ และนี่คือข้อเสียเปรียบที่ร้ายแรงที่สุดในการแก้ปัญหาของเรา สถานการณ์ดังกล่าวควรได้รับการยกเว้นโดยสิ้นเชิงไม่มีบุคคลสองคนที่มีหมายเลขหนังสือเดินทางเดียวกัน แผนที่ที่นี่และคุณสมบัติที่ประกาศมาเพื่อช่วยเหลือเรา (การจัดเก็บข้อมูลเป็นคู่ในรูปแบบ "คีย์" - "ค่า") มาดูการใช้งานแผนที่ที่พบบ่อยที่สุด - คลาสJava HashMapการสร้าง HashMap ใน Java และทำงานกับชั้นเรียน
การใช้งานนี้สร้างได้ง่ายมาก:public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
}
ที่นี่เราได้สร้างพจนานุกรมซึ่งองค์ประกอบต่างๆ จะถูกจัดเก็บในรูปแบบ "สตริงตัวเลข" ตัวเลขจะเป็นคีย์ และสตริงจะเป็นค่า นอกจากนี้เรายังระบุด้วยว่าเราจะมีคีย์ประเภทใด ( Integer
) และเราจะมีค่าประเภทใด ( String
) ทำไมจึงเป็นเช่นนี้? ประการแรกคีย์ใน HashMap จะไม่ซ้ำกันเสมอ วิธีนี้จะได้ผลดีสำหรับเราเพราะเราสามารถใช้หมายเลขหนังสือเดินทางเป็นกุญแจและหลีกเลี่ยงการซ้ำกัน และบรรทัดที่มีชื่อเต็มจะทำหน้าที่เป็นค่า (ชื่อเต็มของบุคคลต่างๆ สามารถเรียกซ้ำได้ง่าย ไม่มีอะไรผิดปกติสำหรับเรา)
การเพิ่มคู่ใหม่ให้กับ HashMap
งานนี้มีลักษณะดังนี้:public class Main {
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
System.out.println(passportsAndNames);
}
}
วิธีนี้ใช้สำหรับสิ่งput()
นี้ นอกจากนี้ HashMap ยังมีวิธีการแทนที่toString()
เพื่อให้สามารถพิมพ์ไปยังคอนโซลได้ ผลลัพธ์จะมีลักษณะดังนี้: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov}
คุณสมบัติของคีย์ HashMap
ทีนี้มาดูกันว่ากุญแจนั้นมีเอกลักษณ์เฉพาะตัวจริง ๆ หรือไม่? เรามาลองเพิ่มองค์ประกอบใหม่ด้วย คีย์ที่มีอยู่ ในแผนที่ แล้ว :public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
passportsAndNames.put(162348, "Viktor Mikhailovich Stychkin");//repeat key
System.out.println(passportsAndNames);
}
ผลลัพธ์: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Viktor Mikhailovich Stychkin} องค์ประกอบก่อนหน้าที่มีคีย์ 162348 อย่างที่คุณเห็น ถูกเขียนทับ “กุญแจ” ถูกเรียกว่ากุญแจด้วยเหตุผล ค่าใน HashMap เข้าถึงได้ด้วยคีย์ (แต่ไม่ใช่ในทางกลับกัน - ไม่สามารถรับคีย์ได้ด้วยค่าเนื่องจากค่าสามารถทำซ้ำได้) สิ่งนี้เห็นได้ชัดเจนในตัวอย่างของการรับองค์ประกอบ เช่นเดียวกับการลบองค์ประกอบออกจาก HashMap:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
String lidiaName = passportsAndNames.get(212133);
System.out.println(lidiaName);
passportsAndNames.remove(162348);
System.out.println(passportsAndNames);
}
ในการรับค่าหรือลบคู่ออกจากพจนานุกรม เราต้องส่งคีย์เฉพาะที่สอดคล้องกับค่านี้ ไปยัง get()
เมธอด ไม่มีดัชนีตัวเลขเช่นเดียวกับในอาร์เรย์หรือรายการใน HashMap - ค่าเข้าถึงได้โดยใช้คีย์ เอาต์พุตคอนโซล: Lidiya Arkadyevna Bublikova {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump}remove()
การตรวจสอบการมีอยู่ของคีย์และค่า
ใน คลาส ArrayListและLinkedListเราสามารถตรวจสอบว่ารายการมีองค์ประกอบเฉพาะหรือไม่ HashMapยังช่วยให้คุณทำเช่นนี้ได้ และสำหรับทั้งสองส่วนของคู่: มันมีวิธีการcontainsKey()
(ตรวจสอบการมีอยู่ของคีย์) และcontainsValue()
(ตรวจสอบการมีอยู่ของค่า)
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
System.out.println(passportsAndNames.containsKey(11111));
System.out.println(passportsAndNames.containsValue("Donald John Trump"));
}
ผลลัพธ์: เท็จ จริง
รับรายการคีย์และค่าทั้งหมด
คุณสมบัติที่สะดวกสบายอีกประการหนึ่งของ HashMap ก็คือ คุณสามารถแยกรายการคีย์ทั้งหมดและค่าทั้งหมดออกจากกันได้ สำหรับสิ่งนี้ วิธีการkeySet()
และ การใช้งาน values()
:
public class Main {
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
Set<Integer> keys = passportsAndNames.keySet();
System.out.println("Keys: " + keys);
ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
System.out.println("Values: " + values);
}
}
กุญแจจะถูกดึงออกมาสู่Set
คอลเลคชัน ลักษณะเฉพาะของมันคือไม่สามารถมีองค์ประกอบที่ซ้ำกัน ตอนนี้สิ่งสำคัญที่ต้องจำก็คือรายการคีย์ทั้งหมดสามารถนำออกจาก HashMap ไปยังคอลเลกชันแยกต่างหากได้ ในตัวอย่างนี้เราบันทึกค่าให้เป็นค่าArrayList
ปกติ เอาต์พุตคอนโซล: คีย์: [212133, 8082771, 162348] ค่า: [Lidiya Arkadyevna Bublikova, Donald John Trump, Ivan Mikhailovich Serebryakov] วิธีsize()
การทำclear()
สิ่งเดียวกันกับในโครงสร้างก่อนหน้านี้ที่เราดำเนินการ: อันแรกส่งคืนองค์ประกอบตัวเลข ในพจนานุกรมในขณะนั้น ส่วนอันที่สองจะลบองค์ประกอบทั้งหมด
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
System.out.println(passportsAndNames.size());
passportsAndNames.clear();
System.out.println(passportsAndNames);
}
ผลลัพธ์: 3 {} เพื่อตรวจสอบว่า HashMap ของเรามีองค์ประกอบอย่างน้อยหนึ่งองค์ประกอบหรือไม่ เราสามารถใช้เมธอดisEmpty()
:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
if (!passportsAndNames.isEmpty()) {
System.out.println(passportsAndNames);
}
}
ผลลัพธ์: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov} ตอนนี้เราจะส่งออกไปยังคอนโซลหลังจากการตรวจสอบเบื้องต้นเท่านั้น :)
รวมสองแผนที่เป็นหนึ่งเดียว
จุดที่น่าสนใจอีกประการหนึ่งคือแผนที่สองแห่งสามารถรวมเป็นหนึ่งเดียวได้ มีวิธีสำหรับสิ่งputAll()
นี้ เราเรียกมันว่าHashMap อันแรก ส่งผ่านอันที่สองเป็นอาร์กิวเมนต์ และองค์ประกอบจากอันที่สองจะถูกเพิ่มเข้าไปในอันแรก:
public static void main(String[] args) {
HashMap<Integer, String> passportsAndNames = new HashMap<>();
HashMap<Integer, String> passportsAndNames2 = new HashMap<>();
passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
passportsAndNames.put(8082771, "Donald John Trump");
passportsAndNames2.put(917352, "Alexey Andreevich Ermakov");
passportsAndNames2.put(925648, "Maxim Olegovich Arkharov");
passportsAndNames.putAll(passportsAndNames2);
System.out.println(passportsAndNames);
}
ผลลัพธ์: {917352=Alexey Andreevich Ermakov, 212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 925648= Maxim Olegovich Arkharov, 162348=Ivan Mikhailovich Serebryakov} องค์ประกอบทั้งหมดของPassportsAndNames2ถูกคัดลอกไปยังPassportsAndNames ตอนนี้เรามาดูตัวอย่างที่ซับซ้อนกว่านี้กัน กล่าวคือ วนซ้ำ HashMap แบบวนซ้ำ
for (Map.Entry entry: passportsAndNames.entrySet()) {
System.out.println(entry);
}
อินเทอร์เฟMap.Entry
ซหมายถึงคู่คีย์-ค่าภายในพจนานุกรม วิธีการentrySet()
ส่งคืนรายการคู่ทั้งหมดใน HashMap ของเรา (เนื่องจากแผนที่ของเราประกอบด้วยคู่รายการดังกล่าว เราจึงวนซ้ำคู่ และไม่แยกคีย์หรือค่า) สรุป: 212133=Lidiya Arkadyevna Bublikova 8082771=Donald John Trump 162348=Ivan Mikhailovich Serebryakov บันทึกบทความนี้สำหรับอนาคต: https://habr.com/ru/post/128017/ ตอนนี้ยังเร็วเกินไปที่จะอ่าน แต่ในอนาคต เมื่อคุณจะได้ลองใช้ HashMap มันจะช่วยให้คุณเข้าใจว่าโครงสร้างข้อมูลนี้ทำงานจากภายในอย่างไร นอกจากนี้ อย่าลืมตรวจสอบเอกสารอย่างเป็นทางการของOracleบน HashMap
GO TO FULL VERSION