web-dev-qa-db-fra.com

Java - Comment créer une nouvelle entrée (clé, valeur)

J'aimerais créer un nouvel élément similaire à Util.Map.Entry qui contiendra la structure key, value.

Le problème est que je ne peux pas instancier un Map.Entry parce que c'est une interface.

Est-ce que quelqu'un sait comment créer un nouvel objet clé/valeur générique pour Map.Entry?

257
Spiderman

Vous pouvez simplement implémenter vous-même l'interface 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;
    }
}

Et puis l'utiliser:

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

Il y a public static class AbstractMap.SimpleEntry<K,V> . Ne laissez pas la partie Abstract du nom vous induire en erreur: c’est en fait PAS une classe abstract (mais son niveau supérieur AbstractMap est ).

Le fait qu'il s'agisse d'une classe imbriquée static signifie que vous DON'T vous avez besoin d'une instance AbstractMap englobante pour l'instancier, afin que quelque chose de similaire soit compilé correctement:

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

Comme indiqué dans une autre réponse, Guava a également une méthode de fabrique static très pratique Maps.immutableEntry que vous pouvez utiliser.


Tu as dit:

Je ne peux pas utiliser _Map.Entry_ lui-même parce qu'apparemment c'est un objet en lecture seule que je ne peux pas instancier de nouveau instanceof

Ce n'est pas tout à fait exact. La raison pour laquelle vous ne pouvez pas l'instancier directement (c'est-à-dire avec new) est qu'il s'agit d'un interface Map.Entry .


Mise en garde et astuce

Comme indiqué dans la documentation, _AbstractMap.SimpleEntry_ est _@since 1.6_, donc si vous êtes bloqué à la version 5.0, il ne vous sera pas disponible.

Pour rechercher une autre classe connue qui _implements Map.Entry_, vous pouvez en fait aller directement au javadoc. De la version Java 6

Interface Map.Entry

Toutes les classes d'implémentation connues :

Malheureusement, version 1.5 ne répertorie aucune classe d'implémentation connue que vous puissiez utiliser. Vous êtes donc peut-être obligé d'implémenter la vôtre.

724
polygenelubricants

Essayez Maps.immutableEntry de Guava

Cela a l'avantage d'être compatible avec Java 5 (contrairement à AbstractMap.SimpleEntry qui nécessite Java 6.)

48
finnw

Exemple de AbstractMap.SimpleEntry:

import Java.util.Map; 
import Java.util.AbstractMap;
import Java.util.AbstractMap.SimpleEntry;

Instancier:

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

Ajouter des lignes:

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

Récupère les lignes:

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

devrait imprimer:

2
3
20
30
2
4

C'est bon pour définir les arêtes des structures de graphes. Comme ceux entre les neurones dans votre tête.

34
Eric Leschinski

A partir de Java 9, il existe une nouvelle méthode utilitaire permettant de créer une entrée immuable qui est Map#entry(Object, Object) .

Voici un exemple simple:

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

Comme il est immuable, appeler setValue lancera un UnsupportedOperationException. Les autres limitations sont le fait que ce n'est pas sérialisable et que null comme clé ou valeur est interdite, si cela ne vous convient pas, vous devrez utiliser AbstractMap.SimpleImmutableEntry ou AbstractMap.SimpleEntry à la place.

NB: Si vous devez créer directement une Map avec 0 à 10 paires maximum (clé, valeur), vous pouvez utiliser à la place les méthodes de type Map.of(K key1, V value1, ...) .

29
Nicolas Filotto

Pourquoi Map.Entry? Je suppose que quelque chose comme une paire clé-valeur est digne de l'affaire.

Utilisez Java.util.AbstractMap.SimpleImmutableEntry ou Java.util.AbstractMap.SimpleEntry

13
tanghao

Vous pourriez en fait aller avec: Map.Entry<String, String> en= Maps.immutableEntry(key, value);

org.Apache.commons.lang3.Tuple.Pair implémente Java.util.Map.Entry et peut également être utilisé de manière autonome.

Comme d'autres l'ont mentionné, la com.google.common.collect.Maps.immutableEntry(K, V) de Guava fait l'affaire.

Je préfère Pair pour sa syntaxe fluide Pair.of(L, R).

6
parxier

J'ai défini une classe Pair générique que j'utilise tout le temps. C'est bien. En prime, en définissant une méthode de fabrique statique (Pair.create), je n'ai qu'à écrire les arguments de type deux fois moins souvent.

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

}
4
Nels Beckman

Si vous utilisez Clojure, vous avez une autre option:

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