แผนที่ Java สั่ง


322

ใน Java มีวัตถุที่ทำหน้าที่เหมือนแผนที่สำหรับการจัดเก็บและการเข้าถึงคู่คีย์ / ค่า แต่สามารถส่งคืนรายการคีย์ที่เรียงลำดับแล้วและรายการค่าที่เรียงลำดับเช่นรายการคีย์และค่าเรียงตามลำดับเดียวกันได้หรือไม่

ดังนั้นตามคำอธิบายโดยใช้รหัสฉันกำลังมองหาบางสิ่งที่มีลักษณะเหมือน OrderedMap ที่เป็นตำนานของฉัน:

OrderedMap<Integer, String> om = new OrderedMap<>();
om.put(0, "Zero");
om.put(7, "Seven");

String o = om.get(7); // o is "Seven"
List<Integer> keys = om.getKeys();
List<String> values = om.getValues();

for(int i = 0; i < keys.size(); i++)
{
    Integer key = keys.get(i);
    String value = values.get(i);
    Assert(om.get(key) == value);
}

4
หากสิ่งที่คุณต้องการทำคือวนซ้ำทั้งสองอย่างในเวลาเดียวกัน Map.entrySet () จะช่วยให้คุณทำสิ่งนั้นได้บนแผนที่ใด ๆ LinkedHashMap มีลำดับที่กำหนดไว้อย่างดี แต่สำหรับ Map ใด ๆ ชุดรายการจะแสดงคู่ของคีย์ / ค่า
Pete Kirkham

5
รหัสนี้ไม่ใช่ตัวอย่างที่ดีเนื่องจากการใช้งานแผนที่จะทำหน้าที่เหมือนกับรหัสตัวอย่างของคุณ เรียงลำดับสั่งซื้อหรือไม่
Peter Lawrey

2
ในการติดตั้ง Sun JDK ชุดส่งคืนโดย getKeys และ getValues ​​() ชุดได้รับการสนับสนุนโดย entrySet () ในแผนที่ดังนั้นจะมีลำดับการทำซ้ำเหมือนกันซึ่งเป็นสิ่งที่คุณทดสอบตัวอย่าง
Pete Kirkham

4
เป็นเรื่องที่น่าสนใจฉันไม่เคยสังเกตว่า ยังคงโทรหาฉันบ้า แต่ฉันไม่ชอบที่จะตั้งสมมติฐานเกี่ยวกับการใช้งานที่ไม่ได้รับการตรวจสอบอย่างชัดเจนจากอินเตอร์เฟซ ฉันถูกเผาหลายครั้งเกินไปในอดีต
Whatsit

2
นี้ควรจะตั้งชื่อเรียง Java แผนที่ตามที่ได้รับคำสั่งแผนที่เป็นสิ่งที่แตกต่างกัน - LinkedHashMapดู
Ondra Žižka

คำตอบ:


397

SortedMapอินเตอร์เฟซ (ที่มีการดำเนินการTreeMap ) ควรจะเป็นเพื่อนของคุณ

อินเทอร์เฟซมีวิธีการ:

  • keySet() ซึ่งส่งคืนชุดของคีย์ตามลำดับจากน้อยไปหามาก
  • values() ซึ่งส่งกลับคอลเลกชันของค่าทั้งหมดตามลำดับจากน้อยไปมากของคีย์ที่เกี่ยวข้อง

ดังนั้นอินเตอร์เฟสนี้จึงตอบสนองความต้องการของคุณได้อย่างแน่นอน อย่างไรก็ตามคีย์ต้องมีลำดับที่มีความหมาย มิฉะนั้นคุณสามารถใช้LinkedHashMapซึ่งคำสั่งนั้นถูกกำหนดโดยคำสั่งแทรก


2
ตัวอย่าง: SortedMap <String, Object> map = new TreeMap <> ();
Ben

7
ในการใช้ TreeMap จำเป็นต้องให้คลาสคีย์นั้นต้องใช้ส่วนต่อประสานที่สามารถเปรียบเทียบได้ ถ้าไม่เช่นนั้น RuntimeException บางประเภทจะถูกโยนทิ้ง TreeMap มันเป็นแผนที่ที่เรียงลำดับแล้ว แต่ฉันคิดว่าผู้เขียนต้องการใช้แผนที่ที่เพิ่งเรียงลำดับ (ไม่ใช่เรียงลำดับ) LinkedHashMap เป็นทางเลือกที่ดีในการรับคำสั่งแผนที่เท่านั้น (ดังที่คุณพูดว่า "พิจารณาจากคำสั่งแทรก")
K. Gol

1
คำตอบนี้อาจได้รับการปรับปรุงโดยการแสดงวิธีการวนซ้ำใน keySet ()

4
จากJava 8 doc LinkedHashMapคำสั่งที่มีการวนซ้ำเป็นคำสั่งที่เข้าถึงได้ล่าสุด
TRiNE

1
@TRiNE ฉันไม่ได้ติดตามความคิดเห็นของคุณ แต่ฉันอาจพลาดบริบทไปบ้าง โดยค่าเริ่มต้นLinkedHashMapของคำสั่งซ้ำคือการแทรกคำสั่ง แต่คุณสามารถใช้ตัวสร้างที่แตกต่างกันเพื่อระบุคำสั่งการเข้าถึงแทน docs.oracle.com/javase/8/docs/api/java/util/…
ปล้น

212

มีวัตถุที่ทำหน้าที่เหมือนแผนที่สำหรับการจัดเก็บและการเข้าถึงคู่คีย์ / ค่า แต่สามารถส่งคืนรายการคีย์ที่เรียงลำดับแล้วและรายการค่าที่เรียงลำดับเช่นรายการคีย์และค่าเรียงตามลำดับเดียวกันได้หรือไม่

คุณกำลังมองหาjava.util.LinkedHashMap คุณจะได้รับรายชื่อของแผนที่ลองคู่<K, V>ซึ่งจะได้รับการวนซ้ำในลำดับเดียวกันเสมอ เพื่อให้เป็นเช่นเดียวกับการสั่งซื้อโดยที่คุณใส่รายการใน. หรือใช้java.util.SortedMapที่ปุ่มทั้งจะต้องมีการสั่งซื้อจากธรรมชาติComparatorหรือจะกำหนดโดย


14
และเพียงบันทึกผู้อ่านตรวจสอบสองครั้งนี้เพราะมันยากที่จะตรวจสอบโดยการทดสอบkeySet()วิธีการส่งคืน LinkedHashSet อย่างมีประสิทธิภาพซึ่งสะท้อนถึงลำดับการput()โทรของคุณ โปรดทราบว่าการโทรซ้ำเพื่อput()รับรหัสเดิมจะไม่เปลี่ยนลำดับเว้นแต่คุณจะได้remove()รับรหัสล่วงหน้า
เกล็นลอเรนซ์

จากJava 8 doc LinkedHashMapคำสั่งที่มีการวนซ้ำเป็นคำสั่งที่เข้าถึงได้ล่าสุด
TRiNE

24

LinkedHashMap จะรักษาลำดับของคีย์

java.util.LinkedHashMap ดูเหมือนจะทำงานเหมือนกับ HashMap ปกติ


1
สิ่งนี้ไม่ได้ให้คำตอบสำหรับคำถาม จะวิจารณ์หรือการร้องขอคำชี้แจงจากผู้เขียนแสดงความคิดเห็นด้านล่างโพสต์ของพวกเขา - คุณสามารถแสดงความคิดเห็นในโพสต์ของคุณเองและเมื่อคุณมีเพียงพอชื่อเสียงคุณจะสามารถที่จะแสดงความคิดเห็นในโพสต์ใด
ianaya89

2
@ ianaya89 ฉันคิดว่านี่เป็นคำตอบที่แท้จริง แต่ก็คล้ายกับคำตอบของ John Feminella มาก !
T30

1
หากคุณต้องการรับแผนที่ที่สั่งซื้อซึ่งจะจัดเก็บรายการไว้ในลำดับนั้นขณะที่คุณใส่ไว้ในแผนที่กว่า LinkedHashMap เป็นคำตอบที่ถูกต้อง หากคุณต้องการเรียงลำดับรายการในรูปแบบแผนที่อิสระตามลำดับที่คุณใส่ไว้กว่า SortedMap คือคำตอบที่ถูกต้อง
Ralph

@TRiNE java 8 doc ที่คุณเชื่อมโยงบอกว่ามีสองโหมดการสั่งซื้อที่เป็นไปได้: การแทรกคำสั่งและการเข้าถึงการสั่งซื้อ คุณคิดว่าอันหลังซึ่งถูกเรียกใช้โดยตัวสร้างสาธารณะพิเศษ LinkedHashMap (int initialCapacity, float loadFactor, บูลีน accessOrder) ตัวสร้างเริ่มต้นสร้างอินสแตนซ์ LinkedHashMap ที่สั่งซื้อโดยแทรก
Artur Łysik

1
@ ArturŁysikใช่มันเป็น ฉันทำผิดพลาดเมื่อหลายวันก่อน ฉันจะแก้ไขมัน ฉันกำลังลบความคิดเห็น เนื่องจากฉันไม่สามารถแก้ไขได้อีกต่อไป
TRiNE

7

ฉันคิดว่าคอลเล็กชันที่ใกล้เคียงที่สุดที่คุณจะได้รับจากเฟรมเวิร์กคือSortedMap


3
ฉันจะลงคะแนนคำตอบนี้ถ้าฉันคิดว่ามันคุ้มค่าเสียคะแนนสำหรับมัน ดังที่คำตอบข้างต้นชี้ให้เห็นคำตอบของคุณขาดข้อมูลที่เหมาะสมเกี่ยวกับ LinkedHashMap และคำอธิบายเล็กน้อยของ SortedMap ก็ดีเช่นกัน
CorayThan

@CorayThan ในกรณีนี้คุณถอนคำตอบที่ดีที่สุดไม่ใช่ downvote ผู้อื่นที่อาจถูกต้อง แต่ไม่ใช่คำตอบที่ดีที่สุด ...
bruno conde

1
นั่นคือสิ่งที่ฉันทำ แค่พูดว่าฉันเข้าใจได้ว่าทำไมบางคนถึงลงคะแนน
CorayThan

5

คุณสามารถใช้ประโยชน์จากส่วนต่อประสานNavigableMapที่สามารถเข้าถึงและสำรวจได้ทั้งขึ้นหรือลง อินเทอร์เฟซนี้มีวัตถุประสงค์เพื่อแทนที่อินเทอร์เฟซ SortedMap แผนที่นำทางมักจะถูกจัดเรียงตามลำดับตามธรรมชาติของปุ่มหรือโดย Comparator ที่มีให้ ณ เวลาที่สร้างแผนที่

: มีสามการใช้งานที่มีประโยชน์มากที่สุดของมันเป็นTreeMap , ImmutableSortedMapและConcurrentSkipListMap

ตัวอย่าง TreeMap:

TreeMap<String, Integer> users = new TreeMap<String, Integer>();
users.put("Bob", 1);
users.put("Alice", 2);
users.put("John", 3);

for (String key: users.keySet()) {
  System.out.println(key + " (ID = "+ users.get(key) + ")");
}

เอาท์พุท:

Alice (ID = 2)
Bob (ID = 1)
John (ID = 3)


4

ตั้งแต่ Java 6 ยังไม่มีการบล็อกเธรดที่ปลอดภัยแทน TreeMap ดูConcurrentSkipListMap


2

TL; DR

หากต้องการMap< Integer , String >เรียงลำดับตามคีย์ให้ใช้คลาสใดคลาสหนึ่งที่ใช้SortedMap/ NavigableMapอินเตอร์เฟส:

  • TreeMap
  • ConcurrentSkipListMap

TreeMapหากจัดการแผนที่ภายในหัวข้อเดียวใช้ครั้งแรก หากจัดการข้ามเธรดให้ใช้อันที่สองConcurrentSkipListMapใช้สอง

สำหรับรายละเอียดโปรดดูตารางด้านล่างและการสนทนาต่อไปนี้

รายละเอียด

นี่คือตารางกราฟิกที่ฉันสร้างขึ้นเพื่อแสดงคุณสมบัติของสิบ Mapการนำไปใช้งานมาพร้อมกับ Java 11

NavigableMapอินเตอร์เฟซที่เป็นสิ่งที่SortedMapควรจะได้รับในสถานที่แรก SortedMapเหตุผลควรจะออก แต่ไม่สามารถเป็นบางส่วนของบุคคลที่ 3 แผนที่การใช้งานอาจจะใช้อินเตอร์เฟซ

ดังที่คุณเห็นในตารางนี้มีเพียงสองคลาสเท่านั้นที่ใช้SortedMap/ NavigableMapอินเตอร์เฟส:

ทั้งสองของคีย์เก็บเหล่านี้เพื่อเรียงตามลำดับธรรมชาติของพวกเขา (โดยใช้compareToวิธีการComparable( https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ Comparable.html ) อินเทอร์เฟซ) หรือการComparatorใช้งานที่คุณผ่าน ความแตกต่างระหว่างทั้งสองชั้นเป็นที่หนึ่งที่สองConcurrentSkipListMapเป็นด้ายปลอดภัยสูงพร้อมกัน

ดูเพิ่มเติมที่คอลัมน์ลำดับการวนซ้ำในตารางด้านล่าง

  • LinkedHashMapระดับผลตอบแทนที่รายการของตนโดยลำดับที่พวกเขาจะถูกแทรกเดิม
  • EnumMapส่งคืนรายการตามลำดับที่กำหนดคลาส enum ของคีย์ของคีย์ที่ถูกกำหนด ตัวอย่างเช่นแผนที่ซึ่งพนักงานครอบคลุมวันใดของสัปดาห์ ( Map< DayOfWeek , Person >) ใช้DayOfWeekคลาส enum ที่สร้างขึ้นใน Java enum นั้นถูกกำหนดด้วยวันจันทร์ก่อนและวันอาทิตย์สุดท้าย ดังนั้นรายการในตัววนซ้ำจะปรากฏตามลำดับนั้น

อีกหกการใช้งานทำให้ไม่สัญญาเกี่ยวกับลำดับที่พวกเขารายงานรายการของพวกเขา

สารบัญการนำแผนที่ไปใช้ใน Java 11 เปรียบเทียบคุณสมบัติ


0

ฉันใช้แผนที่ Simple Hash รายการที่ลิงก์และคอลเล็กชันเพื่อจัดเรียงแผนที่ตามค่า

import java.util.*;
import java.util.Map.*;
public class Solution {

    public static void main(String[] args) {
        // create a simple hash map and insert some key-value pairs into it
        Map<String, Integer> map = new HashMap<String, Integer>();
        map.put("Python", 3);
        map.put("C", 0);
        map.put("JavaScript", 4);
        map.put("C++", 1);
        map.put("Golang", 5);
        map.put("Java", 2);
        // Create a linked list from the above map entries
        List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
        // sort the linked list using Collections.sort()
        Collections.sort(list, new Comparator<Entry<String, Integer>>(){
        @Override
         public int compare(Entry<String, Integer> m1, Entry<String, Integer> m2) {
        return m1.getValue().compareTo(m2.getValue());
        }
      });
      for(Entry<String, Integer> value: list) {
         System.out.println(value);
     }
   }
}

ผลลัพธ์คือ:

C=0
C++=1
Java=2
Python=3
JavaScript=4
Golang=5
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.