Java - Cara membuat Entri baru (kunci, nilai)

291

Saya ingin membuat item baru yang sama dengan Util.Map.Entryyang akan berisi struktur key, value.

Masalahnya adalah saya tidak bisa instantiate Map.Entrykarena itu antarmuka.

Adakah yang tahu cara membuat objek kunci / nilai generik baru untuk Map.Entry?

Manusia laba-laba
sumber

Jawaban:

79

Anda bisa langsung mengimplementasikan Map.Entry<K, V>antarmuka:

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;
    }
}

Dan kemudian menggunakannya:

Map.Entry<String, Object> entry = new MyEntry<String, Object>("Hello", 123);
System.out.println(entry.getKey());
System.out.println(entry.getValue());
Jesper
sumber
117
tentu saja - saya hanya bertanya-tanya apakah tidak ada solusi out-of-the-box untuk itu. Saya mencoba membuat kode saya set standar mungkin ...
Spiderman
1
Bisakah Anda jelaskan mengapa beberapa implementasi Peta memiliki kunci sebagai final (seperti di HashMap, ConcurrentHashMap), tetapi tidak di beberapa implementasi lain seperti TreeMap, WeakHashMap?
AKS
7
Kode yang diberikan tidak sepenuhnya benar karena tidak menimpa sama dengan dan kode hash juga yang diperlukan oleh antarmuka Map.Entry
John Tang Boyland
Pada Java 7 Update 80, saya telah menerapkan di atas dan itu berhasil ( pastebin ). Tidak ada metode lain yang diganti.
perak
807

Ada public static class AbstractMap.SimpleEntry<K,V>. Jangan biarkan Abstractbagian dari nama menyesatkan Anda: itu sebenarnya tidak sebuah abstractkelas (tapi top-level AbstractMapadalah).

Fakta bahwa itu adalah statickelas bersarang berarti bahwa Anda TIDAK perlu menyertakan AbstractMapinstance untuk instantiate, jadi sesuatu seperti ini mengkompilasi dengan baik:

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

Seperti disebutkan dalam jawaban lain, Guava juga memiliki staticmetode pabrik yang nyaman Maps.immutableEntryyang dapat Anda gunakan.


Kamu berkata:

Saya tidak dapat menggunakan Map.Entrydirinya sendiri karena ternyata itu adalah objek hanya-baca yang saya tidak dapat instantiate baruinstanceof

Itu tidak sepenuhnya akurat. Alasan mengapa Anda tidak dapat membuat instantiate secara langsung (yaitu dengan new) adalah karena itu adalah interface Map.Entry.


Peringatan dan tip

Seperti yang tercantum dalam dokumentasi, AbstractMap.SimpleEntryadalah @since 1.6, jadi jika Anda terjebak ke 5.0, maka tidak tersedia untuk Anda.

Untuk mencari kelas lain yang diketahui itu implements Map.Entry, Anda sebenarnya bisa langsung menuju ke javadoc. Dari versi Java 6

Peta Antarmuka. Coba

Semua Kelas Pelaksana yang Dikenal :

Sayangnya versi 1.5 tidak mencantumkan kelas pelaksana yang diketahui yang dapat Anda gunakan, jadi Anda mungkin terjebak dengan penerapan kelas Anda sendiri.

polygenelubricants
sumber
Baris di atas mengembalikan kesalahan kompilasi untuk saya (saya menggunakan java 5, BTW) - pesan kesalahan adalah: 'Tipe AbstractMap.SimpleEntry tidak terlihat'
Spiderman
6
Itu karena AbstractMap.SimpleEntrytidak publik sampai Java 6, seperti yang Anda lihat di dokumentasi.
Jesper
OK, jadi untuk merangkum diskusi singkat - tidak ada solusi out-of-the-box untuk itu di Jawa 5 - saya harus menggunakan implementasi saya sendiri untuk itu.
Spiderman
4
+1 untuk ditunjukkan AbstractMap.SimpleEntry. Saya kira Anda belajar sesuatu yang baru setiap hari!
Priidu Neemre
apa yang Anda maksud dengan melampirkan "contoh AbstractMap terlampir". Apakah Melampirkan menyimpulkan istilah teknis atau sesuatu di java? mohon bimbingannya.
Grafik C
70

Mulai dari Java 9, ada metode utilitas baru yang memungkinkan untuk membuat entri yang tidak dapat diubah Map#entry(Object, Object).

Ini adalah contoh sederhana:

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

Karena tidak berubah, panggilan setValueakan melempar UnsupportedOperationException. Keterbatasan lainnya adalah fakta bahwa itu tidak serializable dan nullkarena kunci atau nilai dilarang, jika itu tidak dapat diterima untuk Anda, Anda harus menggunakan AbstractMap.SimpleImmutableEntryatau AbstractMap.SimpleEntrysebagai gantinya.

NB: Jika kebutuhan Anda adalah untuk membuat secara langsung pasangan Map0 hingga 10 (kunci, nilai), Anda dapat menggunakan metode tipe Map.of(K key1, V value1, ...).

Nicolas Filotto
sumber
53

Coba Maps.immutableEntry dari Guava

Ini memiliki keuntungan karena kompatibel dengan Java 5 (tidak seperti AbstractMap.SimpleEntryyang membutuhkan Java 6.)

menemukan
sumber
34

Contoh AbstractMap.SimpleEntry:

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

Memberi contoh:

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

Tambahkan baris:

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

Ambil baris:

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());

Harus mencetak:

2
3
20
30
2
4

Ini bagus untuk menentukan tepi struktur grafik. Seperti yang ada di antara neuron di kepala Anda.

Eric Leschinski
sumber
18

Anda sebenarnya bisa pergi dengan: Map.Entry<String, String> en= Maps.immutableEntry(key, value);

Juan David Ortega Tapias
sumber
Ini berguna. github.com/google/guava Guava adalah seperangkat pustaka Java inti dari Google yang mencakup jenis koleksi baru (seperti multimap dan multiset), koleksi tak berubah, perpustakaan grafik, dan utilitas untuk konkurensi, I / O, hashing, caching, primitif, string, dan banyak lagi! Ini banyak digunakan pada sebagian besar proyek Java di Google, dan banyak digunakan oleh banyak perusahaan lain juga.
Languoguang
13

Mengapa Map.Entry ? Saya kira sesuatu seperti pasangan kunci-nilai cocok untuk kasus ini.

Gunakan java.util.AbstractMap.SimpleImmutableEntryataujava.util.AbstractMap.SimpleEntry

tanghao
sumber
6

org.apache.commons.lang3.tuple.Pairmengimplementasikan java.util.Map.Entrydan juga bisa digunakan secara mandiri.

Juga seperti orang lain menyebutkan Guava com.google.common.collect.Maps.immutableEntry(K, V) melakukan trik.

Saya lebih suka sintaksnya yang Pairlancar Pair.of(L, R).

parxier
sumber
2
Bolehkah saya menyarankan ImmutablePair?
beluchin
Saya sangat suka kelas org.apache.commons.lang3.tuple.Pair, itu luar biasa!
Laurens Op 't Zandt
Satu-satunya hal yang saya tidak suka tentang itu adalah bahwa ia akan serial ke kiri, kanan, kunci, nilai mana kiri = kunci dan kanan = nilai. Hanya 2 nilai ekstra yang tidak berguna (mungkin) dalam string serial.
Vikrant Goel
4

Saya mendefinisikan kelas Pair generik yang saya gunakan sepanjang waktu. Itu bagus. Sebagai bonus, dengan mendefinisikan metode pabrik statis (Pair.create) saya hanya perlu menulis argumen tipe setengah sering.

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);
    }

}
Nels Beckman
sumber
1
Maaf, saya memposting ini sebelum membaca semua komentar lainnya. Sepertinya Anda menginginkan sesuatu yang termasuk dalam standar lib ...
Nels Beckman
2
Google Guava membuat poin bagus mengapa Pairimplementasi adalah hal yang buruk. Sumber
Ingo Bürk
3

Jika Anda menggunakan Clojure, Anda memiliki opsi lain:

(defn map-entry
  [k v]
  (clojure.lang.MapEntry/create k v))
Radon Rosborough
sumber