Java - Как создать новую запись (ключ, значение)

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

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

Кто-нибудь знает, как создать новый универсальный объект key/value для Map.Entry?

Ответ 1

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

Ответ 2

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

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

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

Как отмечено в другом ответе, Guava также имеет удобный static factory метод Maps.immutableEntry, который вы можете использовать.


Ты сказал:

Я не могу использовать Map.Entry сам, потому что, видимо, это объект только для чтения, который я не могу создать new instanceof

Это не совсем точно. Причина, по которой вы не можете создать экземпляр напрямую (т.е. С new), состоит в том, что она interface Map.Entry.


Предостережение и подсказка

Как указано в документации, AbstractMap.SimpleEntry - @since 1.6, поэтому, если вы застряли до 5.0, то он не доступен для вас.

Чтобы найти другой известный класс, который implements Map.Entry, вы действительно можете перейти непосредственно к javadoc. Из версия Java 6

Интерфейс Map.Entry

Все известные классы реализации:

К сожалению, версия 1.5 не содержит список известных классов реализации, которые вы можете использовать, поэтому вы, возможно, застряли в реализации своих собственных.

Ответ 3

Попробуйте Maps.immutableEntry из Guava

Это имеет то преимущество, что оно совместимо с Java 5 (в отличие от AbstractMap.SimpleEntry, для которого требуется Java 6.)

Ответ 4

Пример AbstractMap.SimpleEntry:

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

Instantiate:

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

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

Ответ 5

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

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

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

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

NB. Если вам нужно напрямую создать Map с парами от 0 до 10 (ключ, значение), вы можете вместо этого использовать методы типа Map.of(K key1, V value1,...).

Ответ 6

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

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

Ответ 7

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

Ответ 8

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

Также, как упоминалось ранее, Guava com.google.common.collect.Maps.immutableEntry(K, V) выполняет трюк.

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

Ответ 9

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

}

Ответ 10

Если вы используете Clojure, у вас есть еще один вариант:

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