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?
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());
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 nouveauinstanceof
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
.
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.
Essayez Maps.immutableEntry de Guava
Cela a l'avantage d'être compatible avec Java 5 (contrairement à AbstractMap.SimpleEntry
qui nécessite Java 6.)
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.
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, ...)
.
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
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)
.
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);
}
}
Si vous utilisez Clojure, vous avez une autre option:
(defn map-entry
[k v]
(clojure.lang.MapEntry/create k v))