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
Звичайно - я просто задумався, чи не існує рішення, яке існує поза коробкою. Я намагаюсь зробити свій код максимально стандартним ...
Павук

1
Чи можете ви пояснити, чому деякі реалізації Map мають ключ як остаточний (наприклад, у HashMap, ConcurrentHashMap), а не в інших реалізаціях, таких як TreeMap, WeakHashMap?
AKS

7
Наведений код не є повністю правильним, оскільки він не переосмислює рівне значення та хеш-код, що вимагається інтерфейсом Map.Entry
Джон Тан Бойленд

Що стосується Java 7 Update 80, я реалізував вище, і це спрацювало ( pastebin ). Інші методи не були відмінені.
срібло

806

Там є 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

Інтерфейсна карта. Вхід

Усі відомі класи втілення :

На жаль, версія 1.5 не містить жодного відомого класу впровадження, який ви можете використовувати, тому, можливо, ви застрягли в реалізації своєї власної.


Вищенаведений рядок для мене повертає помилку компіляції (я використовую java 5, BTW) - повідомлення про помилку: "Тип AbstractMap.SimpleEntry не видно"
Spiderman

6
Це тому, що AbstractMap.SimpleEntryдо Java 6 не було загальнодоступним, як ви бачите в документації.
Jesper

Гаразд, підсумовуючи коротке обговорення - у Java 5 немає його нестандартного рішення - я повинен використовувати для цього власну реалізацію.
Людина-павук

4
+1 для вказівки AbstractMap.SimpleEntry. Я здогадуюсь, щодня ви дізнаєтесь щось нове!
Priidu Neemre

що ви маєте на увазі, додаючи в "додаючий екземпляр AbstractMap". Чи є вкладення висновку технічним терміном чи чимось у Java? будь ласка, направляйте мене.
C графіка

70

Починаючи з Java 9, існує новий корисний метод, що дозволяє створити незмінний запис, який є Map#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, ...).


53

Спробуйте Maps.immutableEntry від Guava

Це має перевагу в тому, що вона сумісна з Java 5 (на відміну від AbstractMap.SimpleEntryнеобхідної Java 6.)


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, що включає нові типи колекцій (такі як мультимапа та мультисети), незмінні колекції, бібліотеку графіків та утиліти для одночасності, вводу / виводу, хешування, кешування, примітиви, струни тощо! Він широко використовується в більшості проектів Java в Google, а також широко використовується багатьма іншими компаніями.
Лангуанг

13

Чому Map.Entry? Я здогадуюсь, що щось на зразок пари ключ-значення підходить для справи.

Використовуйте java.util.AbstractMap.SimpleImmutableEntryабоjava.util.AbstractMap.SimpleEntry


6

org.apache.commons.lang3.tuple.Pair знаряддя java.util.Map.Entry а також можуть використовуватися окремо.

Крім того, як інші згадували, com.google.common.collect.Maps.immutableEntry(K, V)цей трюк робить Гуава .

Я віддаю перевагу Pairйого Pair.of(L, R)синтаксису вільним .


2
Чи можу я ImmutablePairзамість цього запропонувати ?
белучин

Мені дуже подобається клас org.apache.commons.lang3.tuple.Pair, це приголомшливо!
Laurens Op 't Zandt

Єдине, що мені не подобається в цьому, це те, що він стає серіалізованим вліво, вправо, в ключ, значення, де ліворуч = ключ і право = значення. Всього 2 зайвих непотрібних (можливо) значення в серіалізованому рядку.
Vikrant Goel

4

Я визначив загальний клас пари, яким я весь час користуюся. Це чудово. Як бонус, визначаючи статичний заводський метод (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
Вибачте, я опублікував це перед тим, як прочитати всі інші коментарі. Схоже, ви хочете чогось, що входить до стандартної ліб ...
Нельс Бекман

2
Google Guava добре говорить про те, чому Pairреалізація - це погана річ. Джерело
Інго Бюрк

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.