JavaRush /จาวาบล็อก /Random-TH /คำถาม 9 อันดับแรกเกี่ยวกับแผนที่ใน Java
Treefeed
ระดับ

คำถาม 9 อันดับแรกเกี่ยวกับแผนที่ใน Java

เผยแพร่ในกลุ่ม
โปรดทราบว่าแผนที่เป็นข้อมูลที่มีโครงสร้างประกอบด้วยชุดของคู่คีย์-ค่า และแต่ละคีย์สามารถใช้ได้เพียงครั้งเดียวในแผนที่เดียวเท่านั้น หัวข้อนี้ครอบคลุมคำถามพื้นฐาน 9 ข้อเกี่ยวกับการใช้Mapใน Java และคลาสที่นำไปใช้งาน เพื่อความง่าย ฉันจะใช้ลักษณะทั่วไป ใน ตัวอย่าง ดังนั้นผมจะเขียนแค่ Map โดยไม่ระบุตัวระบุ Map แต่คุณสามารถสรุปได้ว่าทั้งสองค่าของKและVเทียบเคียงได้ ซึ่งหมายความว่าKจะขยายComparableและVก็จะขยายComparableด้วยคำถาม 9 อันดับแรกเกี่ยวกับแผนที่ใน Java - 1

0. การแปลงแผนที่เป็นรายการ

ใน Java อินเทอร์เฟซ แผนที่มีคอลเลกชันสามประเภท: ชุดคีย์ ชุดค่า และชุดคีย์-ค่า ทั้งหมดนี้สามารถเปลี่ยนเป็นListaddAll()ได้โดยใช้ Constructor หรือเมธอด ข้อมูลโค้ดต่อไปนี้สาธิตวิธีการสร้างArrayListจากแผนที่
// list of keys
List keyList = new ArrayList(Map.keySet());
//list of values
List valueList = new ArrayList(Map.valueSet());
//list key-value
List entryList = new ArrayList(Map.entrySet());

1. วนซ้ำค่าทั้งหมดในแผนที่

การเดินผ่านคู่คีย์-ค่าแต่ละคู่เป็นขั้นตอนพื้นฐานที่สุดในการเดินผ่านแผนที่ ใน Java แต่ละคู่จะถูกเก็บไว้ในฟิลด์ Map ที่เรียกว่าMap.Entry Map.entrySet()ส่งคืนชุดคีย์-ค่า ดังนั้นวิธีที่มีประสิทธิภาพที่สุดในการวนซ้ำค่าทั้งหมดของ Map คือ:
for(Entry entry: Map.entrySet()) {
  //get the key
  K key = entry.getKey();
  //get value
  V value = entry.getValue();
}
เรายังสามารถใช้Iteratorโดยเฉพาะในเวอร์ชันที่อายุน้อยกว่า JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
  Entry entry = itr.next();
  //get the key
  K key = entry.getKey();
  //get value
  V value = entry.getValue();
}

2. การเรียงลำดับแผนที่ด้วยคีย์

การจัดระเบียบแผนที่ด้วยปุ่มเป็นอีกขั้นตอนหนึ่งที่ใช้กันทั่วไป วิธีแรกคือการเพิ่มMap.Entryลงในรายการ และเรียงลำดับโดยใช้ตัวเปรียบเทียบที่เรียงลำดับตามค่า
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getKey().compareTo(e2.getKey());
  }
});
อีกวิธีหนึ่ง: ใช้SortedMapซึ่งนอกจากจะจัดเรียงคีย์ตามลำดับแล้ว แต่คีย์ทั้งหมดจะต้องรวบรวมComparableหรือได้รับการยอมรับจากผู้เปรียบเทียบ หนึ่งในคลาสที่นำไปใช้SortedMapคือTreeMap ตัวสร้างมันยอมรับตัวเปรียบเทียบ รหัสต่อไปนี้แสดงวิธีเปลี่ยนรหัสปกติMapให้เป็นรหัสที่สั่งซื้อ
SortedMap sortedMap = new TreeMap(new Comparator() {

  @Override
  public int compare(K k1, K k2) {
    return k1.compareTo(k2);
  }

});
sortedMap.putAll(Map);

3. สั่งซื้อแผนที่ตามค่า

การเพิ่มแผนที่ลงในรายการแล้วเรียงลำดับจะใช้ได้ในกรณีนี้ แต่คราวนี้คุณต้องใช้Entry.getValue(). รหัสด้านล่างเกือบจะเหมือนกับเมื่อก่อน
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {

  @Override
  public int compare(Entry e1, Entry e2) {
    return e1.getValue().compareTo(e2.getValue());
  }

});
เรายังคงสามารถใช้มันได้SortedMapในกรณีนี้ แต่เฉพาะในกรณีที่ค่าไม่ซ้ำกันเท่านั้น ในกรณีนี้ คุณสามารถเปลี่ยนคู่คีย์-ค่าให้เป็นคีย์-ค่าได้ วิธีแก้ปัญหานี้มีข้อจำกัดที่รุนแรงและฉันไม่แนะนำ

4. การเริ่มต้นแผนที่แบบคงที่/ไม่เปลี่ยนรูป

เมื่อคุณต้องการให้แผนที่ไม่เปลี่ยนรูป วิธีที่ดีคือการคัดลอกลงในแผนที่ที่ไม่เปลี่ยนรูป เทคนิคการเขียนโปรแกรมเชิงป้องกันนี้จะช่วยให้คุณสร้างแผนที่ที่ไม่เพียงแต่ปลอดภัยต่อการใช้งาน แต่ยังปลอดภัยต่อเธรดด้วย ในการเริ่มต้นแผนที่แบบคงที่/ไม่เปลี่ยนรูป เราสามารถใช้เครื่องมือเริ่มต้นstatic(ดูด้านล่าง) ปัญหาของโค้ดนี้คือแม้จะประกาศ Map เป็น แต่เราstatic finalยังคงสามารถใช้งานได้หลังจากการกำหนดค่าเริ่มต้น เช่น Test.Map.put(3,"three");มันจึงไม่ใช่การไม่เปลี่ยนรูปอย่างแท้จริง ในการสร้างแผนที่ที่ไม่เปลี่ยนรูปโดยใช้ตัวเริ่มต้นแบบคงที่ เราจำเป็นต้องมีคลาสที่ไม่ระบุชื่อขั้นสูง ซึ่งเราจะเพิ่มลงในแผนที่ที่ไม่เปลี่ยนรูปในขั้นตอนการกำหนดค่าเริ่มต้นสุดท้าย โปรดดูส่วนที่สองของรหัส เมื่อUnsupportedOperationException จะถูกส่งออกไป หากคุณเรียกใช้Test.Map.put(3,"three");.
public class Test {

  private static final Map Map;
  static {
    Map = new HashMap();
    Map.put(1, "one");
    Map.put(2, "two");
  }
}
public class Test {

  private static final Map Map;
  static {
    Map aMap = new HashMap();
    aMap.put(1, "one");
    aMap.put(2, "two");
    Map = Collections.unmodifiableMap(aMap);
  }
}
ไลบรารีGuavaยังรองรับวิธีการต่างๆ ในการเริ่มต้นคอลเลกชันแบบคงที่และไม่เปลี่ยนรูป หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับประโยชน์ของยูทิลิตี้คอลเลกชันที่ไม่เปลี่ยนรูปของ Guava โปรดดูส่วน คอลเลกชันที่ไม่เปลี่ยนรูปใน Guava How-to

5. ความแตกต่างระหว่าง HashMap, TreeMap และ Hashtable

มีการใช้งานหลักสามประการของ อินเท อ ร์เฟ ซ Mapใน Java: HashMap , TreeMapและHashtable ความแตกต่างหลักมีดังนี้:
  • ลำดับของทาง . HashMapและ HashTable ไม่รับประกันการเรียงลำดับของแผนที่ โดยเฉพาะอย่างยิ่งพวกเขาไม่รับประกันว่าคำสั่งซื้อจะยังคงเหมือนเดิมเมื่อเวลาผ่านไป แต่TreeMapจะเรียงลำดับค่าทั้งหมดใน "ลำดับตามธรรมชาติ" ของคีย์หรือโดยตัวเปรียบเทียบ
  • คู่คีย์-ค่าที่ถูกต้อง HashMapช่วยให้คุณมีคีย์ Null และค่า Null HashTableไม่อนุญาตให้ใช้คีย์ null หรือค่า null หากTreeMapใช้ลำดับตามธรรมชาติหรือตัวเปรียบเทียบไม่อนุญาตให้ใช้คีย์ Null ข้อยกเว้นจะถูกส่งออกไป
  • การซิงโครไนซ์ ซิงโครไนซ์ เท่านั้นHashTableส่วนที่เหลือไม่ได้ แต่ "หากไม่จำเป็นต้องใช้เธรดที่ปลอดภัย ขอแนะนำให้ใช้" HashMapแทนHashTable
การเปรียบเทียบรายละเอียดเพิ่มเติม
.                       | HashMap | HashTable | TreeMap
-------------------------------------------------------

Упорядочивание          |нет      |нет        | да
null в ключ-meaning    | да-да   | нет-нет   | нет-да
синхронизировано        | нет     | да        | нет
производительность      | O(1)    | O(1)      | O(log n)
воплощение              | корзины | корзины   | красно-чёрное дерево
อ่านเพิ่มเติมเกี่ยวกับHashMap กับ ความสัมพันธ์ ทรีแมป กับ แฮชเทเบิลกับ LinkedHashMap _

6. แผนที่พร้อมการค้นหา/ดูแบบย้อนกลับ

บางครั้งเราต้องการชุดคู่คีย์-คีย์ ซึ่งหมายความว่าค่าจะไม่ซ้ำกันเหมือนกับคีย์ (รูปแบบหนึ่งต่อหนึ่ง) ความสอดคล้องนี้ทำให้คุณสามารถสร้าง "มุมมอง/การค้นหาแบบกลับหัว" บนแผนที่ได้ นั่นคือเราสามารถค้นหาคีย์ได้จากค่าของมัน โครงสร้างข้อมูลนี้เรียกว่าแผนที่แบบสองทิศทางซึ่ง JDK ไม่รองรับ ทั้ง Apache Common Collections และ Guava นำเสนอการใช้งานแผนที่แบบสองทิศทางที่เรียกว่า BidiMap และ BiMap ตามลำดับ ทั้งสองมีข้อจำกัดที่บังคับใช้การแมป 1:1 ระหว่างคีย์และค่า

7. สำเนาแผนที่แบบตื้น

Maps ใน Java เกือบทั้งหมด (หรือทั้งหมด) มีตัวสร้างการคัดลอกสำหรับแผนที่อื่น แต่ขั้นตอนการคัดลอกไม่ซิงโครไนซ์ ซึ่งหมายความว่าเมื่อเธรดหนึ่งคัดลอกแผนที่ เธรดอื่นสามารถเปลี่ยนโครงสร้างของมันได้ เพื่อป้องกันการยกเลิกการซิงโครไนซ์การคัดลอกอย่างกะทันหัน ควรใช้หนึ่งในนั้นในกรณีเช่นCollections.synchronizedMap()นี้
Map copiedMap = Collections.synchronizedMap(Map);
อีกวิธีที่น่าสนใจในการคัดลอกแบบตื้นคือการใช้clone(). แต่ไม่แนะนำแม้แต่ผู้สร้างเฟรมเวิร์กคอลเลกชัน Java Joshua Bloch ในการอภิปราย " Copy Constructor vs. Cloning " เขาเข้ารับตำแหน่ง: ข้อความอ้างอิง: "ฉันมักจะรวมวิธีการโคลนสาธารณะไว้ในชั้นเรียนที่เป็นรูปธรรมเพราะผู้คนคาดหวังให้พวกเขาอยู่ที่นั่น ... น่าเสียดายที่การโคลนนิ่งใช้งานไม่ได้ แต่ เกิดขึ้น ... การโคลนนิ่งเป็นจุดอ่อนและฉันคิดว่าผู้คนควรได้รับการเตือนเกี่ยวกับข้อจำกัดของมัน" ด้วยเหตุนี้ ฉันจึงไม่แสดงให้คุณเห็นวิธีการclone()คัดลอกแผนที่ ด้วยซ้ำ

8. สร้างแผนที่เปล่า

หากMapไม่เปลี่ยนรูป ให้ใช้:
Map = Collections.emptyMap();
หรือใช้รูปลักษณ์อื่นใด ตัวอย่างเช่น:
Map = new HashMap();
จบ
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION