Java Class ที่ใช้ Map และเก็บคำสั่งแทรก?


463

ฉันกำลังมองหาคลาสในจาวาที่มีการเชื่อมโยงค่าคีย์ แต่ไม่ต้องใช้แฮช นี่คือสิ่งที่ฉันกำลังทำอยู่:

  1. Hashtableเพิ่มค่าไป
  2. รับ iterator สำหรับ Hashtable.entrySet()
  3. ทำซ้ำผ่านค่าทั้งหมดและ:
    1. รับMap.Entryตัววนซ้ำ
    2. สร้างออบเจ็กต์ประเภทModule(คลาสที่กำหนดเอง) ตามค่า
    3. เพิ่มคลาสลงใน JPanel
  4. แสดงแผง

ปัญหาเกี่ยวกับสิ่งนี้คือฉันไม่สามารถควบคุมลำดับที่ฉันได้รับค่ากลับมาดังนั้นฉันจึงไม่สามารถแสดงค่าในลำดับที่กำหนดได้ (โดยไม่มีการเข้ารหัสลำดับที่ยาก)

ฉันจะใช้ArrayListหรือVectorนี้ แต่ในภายหลังในรหัสที่ฉันต้องการที่จะคว้าModuleวัตถุสำหรับคีย์ที่กำหนดซึ่งผมไม่สามารถทำอะไรกับหรือArrayListVector

ไม่มีใครรู้ว่ามีคลาส Java อิสระ / โอเพนซอร์สที่จะทำเช่นนี้หรือวิธีการรับค่าออกมาจากHashtableเมื่อพวกเขาถูกเพิ่ม?

ขอบคุณ!


1
คุณไม่จำเป็นต้องใช้ entryset / map.entry คุณสามารถวนซ้ำคีย์และค่าโดยใช้ hashtable.keys เป็นการแจงนับหรือโดยใช้ hashtable.keyset.iterator
John Gardner

5
ฉันใช้เสรีภาพในการเปลี่ยนชื่อเนื่องจากการไม่ใช้แฮชไม่ได้เป็นปัญหา แต่เป็นการรักษาลำดับการแทรก
Joachim Sauer

คำถามที่คล้ายกัน, Java สั่งแผนที่
Basil Bourque

คำตอบ:


734

ผมขอแนะนำให้หรือLinkedHashMap TreeMapA LinkedHashMapเก็บคีย์ตามลำดับที่ถูกแทรกในขณะที่ a TreeMapจะถูกเรียงลำดับผ่านทางComparatorหรือเรียงลำดับตามธรรมชาติComparableขององค์ประกอบ

เนื่องจากไม่จำเป็นต้องจัดเรียงองค์ประกอบLinkedHashMapควรเร็วกว่าสำหรับกรณีส่วนใหญ่ TreeMapมีO(log n)ประสิทธิภาพการทำงานสำหรับcontainsKey, get, putและremoveตาม Javadocs ในขณะที่LinkedHashMapเป็นO(1)สำหรับแต่ละ

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


2
สิ่งนี้จะไม่ทำงานสำหรับฉันเพราะตาม javadocs สิ่งนี้จะให้เฉพาะค่าสั่งซื้อ (ผ่านการเรียกค่า ()) มีวิธีการสั่งซื้อ Map.Entry อินสแตนซ์หรือไม่?
Cory Kendall

1
@CoryKendall: TreeMap ไม่ทำงานหรือไม่ มันควรจะถูกจัดเรียงโดยกุญแจไม่ใช่ตามค่า
Michael Myers

1
ความผิดพลาดของฉันฉันคิดว่าเซตไม่ได้เรียงกัน
Cory Kendall

61
โปรดทราบ: การเรียงลำดับของ TreeMap นั้นขึ้นอยู่กับการเรียงลำดับของปุ่มตามธรรมชาติ: "แผนที่จะเรียงลำดับตามการเรียงลำดับตามธรรมชาติของปุ่ม" LinkedHashMap จะเรียงลำดับการแทรก bij แตกต่างใหญ่!
Jop van Raaij

3
@AlexR: นั่นเป็นจริงเฉพาะถ้า LinkedHashMap ถูกสร้างขึ้นโดยใช้Constructor พิเศษซึ่งจัดทำขึ้นเพื่อวัตถุประสงค์นั้น โดยค่าเริ่มต้นการวนซ้ำอยู่ในลำดับการแทรก
Michael Myers

22

LinkedHashMap จะส่งคืนองค์ประกอบตามลำดับที่แทรกเข้าไปในแผนที่เมื่อคุณวนซ้ำใน keySet (), entrySet () หรือค่า () ของแผนที่

Map<String, String> map = new LinkedHashMap<String, String>();

map.put("id", "1");
map.put("name", "rohan");
map.put("age", "26");

for (Map.Entry<String, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + " = " + entry.getValue());
}

สิ่งนี้จะพิมพ์องค์ประกอบตามลำดับที่ใส่ลงในแผนที่:

id = 1
name = rohan 
age = 26 

16

หากแผนที่ที่ไม่เปลี่ยนรูปแบบเหมาะสมกับความต้องการของคุณมีห้องสมุดโดย google ชื่อguava (ดูคำถามฝรั่ง )

GuavaจัดเตรียมImmutableMapพร้อมคำสั่งการทำซ้ำที่ผู้ใช้ระบุไว้อย่างน่าเชื่อถือ ImmutableMapนี้มีประสิทธิภาพ O (1) สำหรับ containKey รับ ไม่สนับสนุนการใส่และลบอย่างชัดเจน

วัตถุImmutableMapถูกสร้างขึ้นโดยใช้วิธีการคงความสะดวกสบายที่หรูหราของ ()และcopyOf ()หรือวัตถุตัวสร้าง


6

คุณสามารถรักษาMap(สำหรับการค้นหาอย่างรวดเร็ว) และList(สำหรับการสั่งซื้อ) แต่ a LinkedHashMapอาจจะง่ายที่สุด คุณสามารถลองSortedMapเช่นTreeMapซึ่งคำสั่งซื้อใด ๆ ที่คุณระบุ


1

ฉันไม่รู้ว่ามันเป็น opensource หรือไม่ แต่หลังจาก googling นิดหน่อยฉันก็พบว่าการใช้ Map โดยใช้ ArrayListนี้ ดูเหมือนว่าจะเป็น pre-1.5 Java ดังนั้นคุณอาจต้องการทำให้เป็นมาตรฐานซึ่งน่าจะง่าย โปรดทราบว่าการนำไปใช้นี้มีการเข้าถึง O (N) แต่สิ่งนี้ไม่น่าจะมีปัญหาหากคุณไม่เพิ่มวิดเจ็ตหลายร้อยรายการใน JPanel ซึ่งคุณไม่ควรทำอยู่ดี



1

เมื่อใดก็ตามที่ฉันต้องการรักษาลำดับธรรมชาติของสิ่งต่าง ๆ ที่ทราบล่วงหน้าฉันจะใช้EnumMap

กุญแจจะเป็น enums และคุณสามารถแทรกในลำดับใดก็ได้ที่คุณต้องการ แต่เมื่อคุณวนซ้ำมันจะวนซ้ำตามลำดับ enum (ลำดับธรรมชาติ)

นอกจากนี้เมื่อใช้ EnumMap ไม่ควรมีการชนซึ่งจะมีประสิทธิภาพมากกว่า

ฉันพบว่าการใช้ enumMap นั้นทำให้อ่านโค้ดได้ง่าย นี่คือตัวอย่าง


1

คุณสามารถใช้LinkedHashMapเพื่อลำดับการแทรกหลักในแผนที่

จุดสำคัญเกี่ยวกับคลาส Java LinkedHashMap คือ:

  1. มันมีองค์ประกอบที่ไม่ซ้ำกันเท่านั้น
  2. LinkedHashMap มีค่าตามคีย์ 3. มันอาจมีคีย์ null หนึ่งและหลายค่า null 4. มันเหมือนกับ HashMap แทนที่จะเก็บรักษาลำดับการแทรก

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> 

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


0

ไม่ว่าคุณจะใช้LinkedHashMap<K, V>หรือคุณสามารถนำCustomMap มาใช้ซึ่งเป็นของตัวเอง

คุณสามารถใช้การติดตามCustomHashMapพร้อมกับคุณสมบัติต่อไปนี้:

  • รักษาคำสั่งแทรกโดยใช้ LinkedHashMap ภายใน
  • nullไม่อนุญาตให้ใช้คีย์ที่มีหรือสตริงว่าง
  • เมื่อคีย์พร้อมค่าถูกสร้างขึ้นเราจะไม่แทนที่ค่าของมัน

HashMapเทียบLinkedHashMapกับCustomHashMap

interface CustomMap<K, V> extends Map<K, V> {
    public boolean insertionRule(K key, V value);
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public class CustomHashMap<K, V> implements CustomMap<K, V> {
    private Map<K, V> entryMap;
    // SET: Adds the specified element to this set if it is not already present.
    private Set<K> entrySet;

    public CustomHashMap() {
        super();
        entryMap = new LinkedHashMap<K, V>();
        entrySet = new HashSet();
    }

    @Override
    public boolean insertionRule(K key, V value) {
        // KEY as null and EMPTY String is not allowed.
        if (key == null || (key instanceof String && ((String) key).trim().equals("") ) ) {
            return false;
        }

        // If key already available then, we are not overriding its value.
        if (entrySet.contains(key)) { // Then override its value, but we are not allowing
            return false;
        } else { // Add the entry
            entrySet.add(key);
            entryMap.put(key, value);
            return true;
        }
    }
    public V put(K key, V value) {
        V oldValue = entryMap.get(key);
        insertionRule(key, value);
        return oldValue;
    }
    public void putAll(Map<? extends K, ? extends V> t) {
        for (Iterator i = t.keySet().iterator(); i.hasNext();) {
            K key = (K) i.next();
            insertionRule(key, t.get(key));
        }
    }

    public void clear() {
        entryMap.clear();
        entrySet.clear();
    }
    public boolean containsKey(Object key) {
        return entryMap.containsKey(key);
    }
    public boolean containsValue(Object value) {
        return entryMap.containsValue(value);
    }
    public Set entrySet() {
        return entryMap.entrySet();
    }
    public boolean equals(Object o) {
        return entryMap.equals(o);
    }
    public V get(Object key) {
        return entryMap.get(key);
    }
    public int hashCode() {
        return entryMap.hashCode();
    }
    public boolean isEmpty() {
        return entryMap.isEmpty();
    }
    public Set keySet() {
        return entrySet;
    }
    public V remove(Object key) {
        entrySet.remove(key);
        return entryMap.remove(key);
    }
    public int size() {
        return entryMap.size();
    }
    public Collection values() {
        return entryMap.values();
    }
}

การใช้งานของCustomHashMap:

public static void main(String[] args) {
    System.out.println("== LinkedHashMap ==");
    Map<Object, String> map2 = new LinkedHashMap<Object, String>();
    addData(map2);

    System.out.println("== CustomHashMap ==");
    Map<Object, String> map = new CustomHashMap<Object, String>();
    addData(map);
}
public static void addData(Map<Object, String> map) {
    map.put(null, "1");
    map.put("name", "Yash");
    map.put("1", "1 - Str");
    map.put("1", "2 - Str"); // Overriding value
    map.put("", "1"); // Empty String
    map.put(" ", "1"); // Empty String
    map.put(1, "Int");
    map.put(null, "2"); // Null

    for (Map.Entry<Object, String> entry : map.entrySet()) {
        System.out.println(entry.getKey() + " = " + entry.getValue());
    }
}

O / P:

== LinkedHashMap == | == CustomHashMap ==
null = 2            | name = Yash
name = Yash         | 1 = 1 - Str
1 = 2 - Str         | 1 = Int
 = 1                |
  = 1               |
1 = Int             |

หากคุณรู้ว่า KEY ได้รับการแก้ไขแล้วคุณสามารถใช้ EnumMap ได้ รับค่าจากไฟล์ Properties / XML

EX:

enum ORACLE {
    IP, URL, USER_NAME, PASSWORD, DB_Name;
}

EnumMap<ORACLE, String> props = new EnumMap<ORACLE, String>(ORACLE.class);
props.put(ORACLE.IP, "127.0.0.1");
props.put(ORACLE.URL, "...");
props.put(ORACLE.USER_NAME, "Scott");
props.put(ORACLE.PASSWORD, "Tiget");
props.put(ORACLE.DB_Name, "MyDB");
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.