Comment utiliser Sets comme clés dans Java Maps
J'ai une Carte qui utilise un Ensemble pour le type de clé, comme ceci:
Map<Set<Thing>, Val> map;
Quand j'ai une requête de la carte.containsKey(myBunchOfThings), elle retourne false, et je ne comprends pas pourquoi. Je peut itérer sur chaque touche du clavier et vérifier qu'il y a une clé (1) a le même hashCode, et (2) est égal à() à myBunchOfThings.
System.out.println(map.containsKey(myBunchOfThings)); //false.
for (Set<Thing> k : map.keySet()) {
if (k.hashCode() == myBunchOfThings.hashCode() && k.equals(myBunchOfThings) {
System.out.println("Fail at life."); //it prints this.
}
}
Dois-je simplement fondamentalement mal compris le contrat pour containsKey? Est-il un secret à l'aide des ensembles (ou, plus généralement, des collections) que des clés, des cartes?
source d'informationauteur Gabe Johnson
Vous devez vous connecter pour publier un commentaire.
Clé ne doit pas être muté sur la carte. Le
Map
java doc a dit:Je savais ce problème, mais n'a jamais fait le test, jusqu'à présent. J'élabore ensuite un peu plus:
Après
key2
est muté, la carte ne contient pas de plus. On pourrait penser que la carte des "indices" sur les données ajoutées et nous attendons à ce qu'il contient encore le key2 clone (ligne marquée avec*
). Mais assez drôle, ce n'est pas le cas.Donc, comme la java doc a dit, les clés ne doivent pas être muté sinon le comportement est non spécifié. Période.
Je suppose que c'est ce qui se passe dans votre cas.
Vous devriez vous efforcer d'utiliser immuable types de clés pour les
Map
s. Les Collections et les jeux sont généralement très facilement mutable donc sont généralement une mauvaise idée de l'utiliser de cette façon.Si vous souhaitez utiliser plusieurs valeurs importantes comme
Map
clé que vous devez utiliser une implémentation de la classe conçu pour cet usage, comme Apache Commons CollectionsMultiKey
.Si vous devez vraiment utiliser un Ensemble ou d'une Collection comme une clé, assurez-vous qu'il immuable (
Collections.unmodifiableSet(...)
) et puis ne pas faire référence à la mutable sauvegarde de l'objet.Une autre difficulté avec l'aide de Collections comme les clés, c'est qu'ils ont pu être construites dans un ordre différent. Seulement une collection triée avez de fortes chances de hotte de correspondance. Par exemple, si vous utilisez un suivant un ordre séquentiel
ArrayList
mais de construire la liste d'une manière différente la deuxième fois, il ne sera pas correspondre à la clé, le code de hachage et l'ordre des valeurs est différente.MODIFIER: je corrige la position des mains sur cette déclaration, ci-dessous, n'ayant jamais eu à utiliser Ensemble pour un ket. Je viens de lire une partie de la hashCode de la mise en œuvre dans AbstractHashSet. Il utilise un simple total de toutes les valeurs n'est donc pas dépendante de la commande. Est égal vérifie également qu'un ensemble contient toutes les valeurs de l'autre. Cependant, ceci est encore vrai avec d'autres types de Collections en Java (ArrayList ordre a de l'importance).
Si votre collection est en fait une
HashSet
la création de l'ordre peut importe. En fait un hachage de la collection gérée de toute nature sera encore plus problématique que toute l'évolution de la capacité de déclencher une reconstruction de l'ensemble de la collection qui peut réorganiser les éléments. Pensez à des collisions de hachages qui sont stockées dans l'ordre de la collision (une simple liés de la chaîne de tous les éléments où la transformation de la valeur de hachage est le même).Avez-vous modifier le jeu après l'insertion? Si oui, il est possible de la définir ai trié dans un autre seau que celui qu'il cherche. Lors d'une itération, il n'trouver votre jeu, parce qu'il semble dans l'ensemble de la carte.
Je crois que le contrat pour HashMap unis, vous n'êtes pas autorisé à modifier le hashcode pour les objets utilisés comme un élément clé,
Vous êtes de passage le jeu exact (le jeu que vous voulez trouver) lors de la comparaison pour la clé?