Java - วิธีสร้างรายการใหม่ (คีย์, ค่า)


291

ฉันต้องการสร้างรายการใหม่ที่คล้ายกับUtil.Map.Entryที่จะมีโครงสร้างkey, value.

ปัญหาคือฉันไม่สามารถสร้างอินสแตนซ์ได้Map.Entryเนื่องจากเป็นส่วนต่อประสาน

ไม่มีใครรู้วิธีสร้างวัตถุคีย์ / ค่าทั่วไปใหม่สำหรับ Map.Entry

คำตอบ:


79

คุณสามารถใช้Map.Entry<K, V>อินเทอร์เฟซได้ด้วยตนเอง:

import java.util.Map;

final class MyEntry<K, V> implements Map.Entry<K, V> {
    private final K key;
    private V value;

    public MyEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }

    @Override
    public K getKey() {
        return key;
    }

    @Override
    public V getValue() {
        return value;
    }

    @Override
    public V setValue(V value) {
        V old = this.value;
        this.value = value;
        return old;
    }
}

แล้วใช้มัน:

Map.Entry<String, Object> entry = new MyEntry<String, Object>("Hello", 123);
System.out.println(entry.getKey());
System.out.println(entry.getValue());

117
แน่นอน - ฉันแค่สงสัยว่าไม่มีวิธีแก้ปัญหานอกกรอบหรือไม่ ฉันกำลังพยายามที่จะทำให้รหัสของฉันเป็นมาตรฐานที่เป็นไปได้ ...
Spiderman

1
คุณช่วยอธิบายได้ไหมว่าทำไมการใช้งานแผนที่บางอย่างจึงมีคีย์เป็นขั้นตอนสุดท้าย (เช่นใน HashMap, ConcurrentHashMap) แต่ไม่ใช่ในการดำเนินการอื่น ๆ เช่น TreeMap, WeakHashMap?
AKS

7
รหัสที่ระบุไม่ถูกต้องอย่างสมบูรณ์เนื่องจากมันไม่ได้แทนที่เท่ากับและ hashCode ด้วยซึ่งจำเป็นต้องใช้โดยอินเตอร์เฟส Map.Entry
John Tang Boyland

ในฐานะของ Java 7 Update 80 ฉันได้ดำเนินการด้านบนและใช้งานได้ ( pastebin ) ไม่มีวิธีการอื่นถูกแทนที่
เงิน

807

public static class AbstractMap.SimpleEntry<K,V>มี อย่าปล่อยให้Abstractส่วนหนึ่งของชื่อคุณเข้าใจผิด: มันเป็นในความเป็นจริงไม่abstractระดับ ( แต่ระดับบนสุดAbstractMapคือ)

ความจริงที่ว่ามันเป็นstaticคลาสที่ซ้อนกันหมายความว่าคุณไม่จำเป็นต้องมีAbstractMapอินสแตนซ์ที่ล้อมรอบเพื่อยกตัวอย่างมันดังนั้นสิ่งที่คอมไพล์นี้รวบรวมได้:

Map.Entry<String,Integer> entry =
    new AbstractMap.SimpleEntry<String, Integer>("exmpleString", 42);

ดังที่ได้กล่าวไว้ในคำตอบอื่น Guava ยังมีstaticวิธีการใช้Maps.immutableEntryที่สะดวกจากโรงงานซึ่งคุณสามารถใช้ได้


คุณพูดว่า:

ฉันไม่สามารถใช้Map.Entryตัวเองเพราะเห็นได้ชัดว่ามันเป็นวัตถุแบบอ่านอย่างเดียวที่ฉันไม่สามารถสร้างอินสแตนซ์ใหม่ได้instanceof

นั่นไม่ถูกต้องทั้งหมด เหตุผลที่คุณไม่สามารถยกตัวอย่างได้โดยตรง (คือมีnew) interface Map.Entryเป็นเพราะมันเป็น


ข้อแม้และเคล็ดลับ

ดังที่ระบุไว้ในเอกสารประกอบAbstractMap.SimpleEntryคือ@since 1.6หากคุณติดอยู่ที่ 5.0 แสดงว่าคุณไม่สามารถใช้งานได้

เพื่อมองหาอีกคลาสที่รู้จักกันดีว่า implements Map.Entryในความเป็นจริงคุณสามารถไปที่ javadoc โดยตรง จากเวอร์ชัน Java 6

อินเตอร์เฟส Map.Entry

คลาสการใช้งานที่รู้จักทั้งหมด :

น่าเสียดายที่รุ่น 1.5ไม่ได้ระบุคลาสการใช้งานที่รู้จักซึ่งคุณสามารถใช้ได้ดังนั้นคุณอาจติดอยู่กับการใช้งานของคุณเอง


บรรทัดข้างต้นส่งกลับข้อผิดพลาดการคอมไพล์สำหรับฉัน (ฉันใช้ java 5, BTW) - ข้อความแสดงข้อผิดพลาดคือ: 'ไม่พบประเภท AbstractMap.SimpleEntry'
Spiderman

6
นั่นเป็นเพราะAbstractMap.SimpleEntryยังไม่เปิดเผยจนกว่า Java 6 อย่างที่คุณเห็นในเอกสารประกอบ
Jesper

ตกลงดังนั้นเพื่อสรุปการอภิปรายสั้น ๆ - ไม่มีทางออกที่นอกกรอบใน Java 5 - ฉันควรใช้การปรับใช้ของตัวเอง
Spiderman

4
+1 AbstractMap.SimpleEntryสำหรับการชี้ให้เห็น ฉันเดาว่าคุณเรียนรู้สิ่งใหม่ทุกวัน!
Priidu Neemre

คุณหมายถึงอะไรโดยการใส่ใน "อินสแตนซ์ AbstractMap ที่ล้อมรอบ" การปิดล้อมเป็นการอนุมานศัพท์เทคนิคหรืออะไรบางอย่างใน java หรือไม่? กรุณาแนะนำฉัน
กราฟิก C

70

เริ่มต้นจากJava 9Map#entry(Object, Object)มีวิธีที่อาคารใหม่ที่ช่วยให้การสร้างรายการที่ไม่เปลี่ยนรูปซึ่งเป็น

นี่คือตัวอย่างง่ายๆ:

Entry<String, String> entry = Map.entry("foo", "bar");

ในขณะที่มันจะไม่เปลี่ยนรูปโทรจะโยนsetValue UnsupportedOperationExceptionข้อ จำกัด อื่น ๆ นั้นเป็นข้อเท็จจริงที่ว่ามันไม่ได้เป็นแบบอนุกรมและnullเป็นกุญแจสำคัญหรือค่าเป็นสิ่งต้องห้ามหากคุณไม่ได้รับการยอมรับคุณจะต้องใช้AbstractMap.SimpleImmutableEntryหรือAbstractMap.SimpleEntryแทน

หมายเหตุ:หากคุณต้องการสร้างคู่ที่Mapมี 0 ถึง 10 (คีย์, ค่า) โดยตรงคุณสามารถใช้วิธีการประเภทMap.of(K key1, V value1, ...)แทน



34

ตัวอย่างของ AbstractMap.SimpleEntry:

import java.util.Map; 
import java.util.AbstractMap;
import java.util.AbstractMap.SimpleEntry;

ยกตัวอย่าง:

ArrayList<Map.Entry<Integer, Integer>> arr = 
    new ArrayList<Map.Entry<Integer, Integer>>();

เพิ่มแถว:

arr.add(new AbstractMap.SimpleEntry(2, 3));
arr.add(new AbstractMap.SimpleEntry(20, 30));
arr.add(new AbstractMap.SimpleEntry(2, 4));

ดึงแถว:

System.out.println(arr.get(0).getKey());
System.out.println(arr.get(0).getValue());
System.out.println(arr.get(1).getKey());
System.out.println(arr.get(1).getValue());
System.out.println(arr.get(2).getKey());
System.out.println(arr.get(2).getValue());

ควรพิมพ์:

2
3
20
30
2
4

มันเป็นการดีสำหรับการกำหนดขอบของโครงสร้างกราฟ เหมือนเซลล์ประสาทในหัวของคุณ


18

คุณสามารถไปกับ: Map.Entry<String, String> en= Maps.immutableEntry(key, value);


มันมีประโยชน์ github.com/google/guava Guava เป็นชุดของไลบรารี Java หลักจาก Google ที่มีประเภทคอลเลกชันใหม่ (เช่น Multimap และ Multiset), คอลเล็กชันที่ไม่เปลี่ยนรูปแบบ, ไลบรารีกราฟและยูทิลิตี้สำหรับการทำงานพร้อมกัน, I / O, hashing, แคช ดึกดำบรรพ์สายและอื่น ๆ ! มันถูกใช้อย่างกว้างขวางในโครงการ Java ส่วนใหญ่ภายใน Google และใช้กันอย่างแพร่หลายโดย บริษัท อื่น ๆ อีกมากมายเช่นกัน
Languoguang

13

ทำไม Map.Entry ? ฉันเดาบางอย่างเช่นคู่คีย์ - ค่าเหมาะสำหรับเคส

ใช้java.util.AbstractMap.SimpleImmutableEntryหรือjava.util.AbstractMap.SimpleEntry


6

org.apache.commons.lang3.tuple.Pairใช้java.util.Map.Entryและสามารถใช้แบบสแตนด์อโลนได้

เช่นเดียวกับคนอื่น ๆ ที่กล่าวถึง Guava com.google.common.collect.Maps.immutableEntry(K, V)ไม่หลอกลวง

ฉันชอบไวยากรณ์ที่Pairคล่องแคล่วPair.of(L, R)


2
ฉันขอแนะนำImmutablePairแทนได้ไหม
beluchin

ฉันชอบคลาส org.apache.commons.lang3.tuple.Pair มันยอดเยี่ยมมาก!
Laurens Op 't Zandt

สิ่งเดียวที่ฉันไม่ชอบคือมันได้รับการทำให้เป็นอนุกรมไปทางซ้ายขวาคีย์ค่าที่ left = key และ right = value มีเพียง 2 ค่า (อาจ) ที่ไร้ประโยชน์ในสตริงที่ต่อเนื่องกัน
Vikrant Goel

4

ฉันกำหนดคลาส Pair สามัญที่ฉันใช้ตลอดเวลา มันเยี่ยมมาก เป็นโบนัสโดยการกำหนดวิธีคงที่จากโรงงาน (Pair.create) ฉันต้องเขียนอาร์กิวเมนต์ชนิดครึ่งบ่อยครั้ง

public class Pair<A, B> {

    private A component1;
    private B component2;

    public Pair() {
            super();
    }

    public Pair(A component1, B component2) {
            this.component1 = component1;
            this.component2 = component2;
    }

    public A fst() {
            return component1;
    }

    public void setComponent1(A component1) {
            this.component1 = component1;
    }

    public B snd() {
            return component2;
    }

    public void setComponent2(B component2) {
            this.component2 = component2;
    }

    @Override
    public String toString() {
            return "<" + component1 + "," + component2 + ">";
    }

    @Override
    public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result
                            + ((component1 == null) ? 0 : component1.hashCode());
            result = prime * result
                            + ((component2 == null) ? 0 : component2.hashCode());
            return result;
    }

    @Override
    public boolean equals(Object obj) {
            if (this == obj)
                    return true;
            if (obj == null)
                    return false;
            if (getClass() != obj.getClass())
                    return false;
            final Pair<?, ?> other = (Pair<?, ?>) obj;
            if (component1 == null) {
                    if (other.component1 != null)
                            return false;
            } else if (!component1.equals(other.component1))
                    return false;
            if (component2 == null) {
                    if (other.component2 != null)
                            return false;
            } else if (!component2.equals(other.component2))
                    return false;
            return true;
    }

    public static <A, B> Pair<A, B> create(A component1, B component2) {
            return new Pair<A, B>(component1, component2);
    }

}

1
ขออภัยฉันโพสต์สิ่งนี้ก่อนที่จะอ่านความคิดเห็นอื่น ๆ ทั้งหมด ดูเหมือนว่าคุณต้องการสิ่งที่รวมอยู่ใน lib มาตรฐาน ...
Nels เบคค์

2
Google Guava สร้างจุดที่ดีว่าทำไมPairการติดตั้งใช้งานจึงเป็นสิ่งที่ไม่ดี แหล่งที่มา
Ingo Bürk

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.