Java - Как создать новую запись (ключ, значение) - PullRequest
249 голосов
/ 24 июня 2010

Я хотел бы создать новый элемент, аналогичный Util.Map.Entry, который будет содержать структуру key, value.

Проблема в том, что я не могу создать экземпляр Map.Entry, потому чтоэто интерфейс.

Кто-нибудь знает, как создать новый объект общего ключа / значения для Map.Entry?

Ответы [ 10 ]

704 голосов
/ 24 июня 2010

Там public static class AbstractMap.SimpleEntry<K,V>. Не позволяйте части Abstract названия вводить вас в заблуждение: на самом деле это NOT abstract класс (но его верхний уровень AbstractMap равен).

Тот факт, что это вложенный класс static означает, что вам НЕ нужен включающий экземпляр AbstractMap для его создания, поэтому что-то вроде этого компилируется нормально:

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

Как отмечалось в другом ответе, в Гуаве также есть удобный 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 версия не содержит ни одного известного класса реализации, который вы можете использовать, так что вы, возможно, застряли в реализации своего собственного.

76 голосов
/ 24 июня 2010

Вы можете просто реализовать интерфейс 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());
45 голосов
/ 24 июня 2010

Попробуйте Maps.immutableEntry из Гуава

Преимущество заключается в совместимости с Java 5 (в отличие от AbstractMap.SimpleEntry, для которого требуется Java 6.)

33 голосов
/ 27 сентября 2015

Пример 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

Это хорошо для определения краевграфовых структур.Как между нейронами в твоей голове.

23 голосов
/ 20 сентября 2018

Начиная с Java 9, есть новый служебный метод, позволяющий создать неизменяемую запись, которая Map#entry(Object, Object).

Вот простой пример:

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

Поскольку он неизменен, при вызове setValue будет UnsupportedOperationException. Другими ограничениями является тот факт, что он не сериализуем и запрещен null в качестве ключа или значения; если он неприемлем для вас, вам нужно будет использовать AbstractMap.SimpleImmutableEntry или AbstractMap.SimpleEntry вместо.

13 голосов
/ 26 ноября 2013

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

Используйте java.util.AbstractMap.SimpleImmutableEntry или java.util.AbstractMap.SimpleEntry

9 голосов
/ 08 ноября 2018

Вы могли бы пойти с: Map.Entry<String, String> en= Maps.immutableEntry(key, value);

6 голосов
/ 19 ноября 2012

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

Также, как другие упоминали, Guava's com.google.common.collect.Maps.immutableEntry(K, V) делает трюк.

Я предпочитаю Pair за его свободный Pair.of(L, R) синтаксис.

4 голосов
/ 24 июня 2010

Я определил общий класс 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);
    }

}
3 голосов
/ 19 июля 2016

Если вы используете Clojure, у вас есть другая опция:

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