Maison >Java >javaDidacticiel >Comment modifier la valeur dans Hashmap en fonction de la valeur clé en Java
S'il n'y a pas de clé dans la carte d'origine, elle sera créée. S'il y a la clé d'origine, la valeur d'origine sera écrasée par la valeur
map.put(key,value);.
Cette implémentation en ajoute un à la valeur d'origine (prémisse Il y a cette clé)
map.put(key,map.get(key)+1);
La valeur correspondant à la clé peut être obtenue comme suit. Sinon, la valeur par défaut peut être renvoyée
map.getOrDefault(key,value);
Une série de paires clé-valeur stockées dans HashMap, où la clé est un type personnalisé. Après l'avoir mis dans HashMap, nous modifions les attributs d'une certaine clé en externe, puis nous utilisons cette clé pour supprimer des éléments de HashMap. Que retournera HashMap à ce moment-là ?
Les réponses de plusieurs personnes dans notre bureau sont incohérentes. Certains disent qu'il renvoie null, et d'autres disent qu'il peut renvoyer une valeur normalement. Mais quelle que soit la réponse, il n’y a aucune raison solide. J'ai pensé que cette question était assez intéressante, alors j'ai écrit un test de code. Le résultat est nul. Il convient de noter que notre classe personnalisée remplace la méthode hashCode. Je pense que ce résultat est un peu inattendu, car nous savons que HashMap stocke les types de référence et nous avons mis à jour la clé à l'extérieur, ce qui signifie que la clé dans HashMap est également mise à jour, ce qui signifie que la valeur de retour hashCode de cette clé se produira également . changement. À ce stade, le hashCode de key et HashMap doit être le même que le hashCode de l'élément, et égal à retournera certainement vrai, car il s'agit du même objet, alors pourquoi ne peut-il pas renvoyer la valeur correcte ?
Il y a 2 cas ici, l'un est la classe Person et l'autre est la classe Student. Vérifions le point de vue ci-dessus (avec conclusion) :
Si la modification des propriétés de l'objet changera son. hashcode => Oui
L'attribut sera-t-il affecté par la modification de la valeur lors de l'accès au HashMap => La valeur est nulle
package tech.luxsun.interview.luxinterviewstarter.collection; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.HashMap; /** * @author Lux Sun * @date 2021/4/22 */ public class MapDemo0 { public static void main(String[] args) { HashMap<Object, Object> map = new HashMap<>(); // Person Case Person p = new Person("Bob", 12); map.put(p, "person"); System.out.println(p.hashCode()); System.out.println(map.get(p)); p.setAge(13); System.out.println(p.hashCode()); System.out.println(map.get(p)); // Student Case Student stu = new Student("Bob", 12); map.put(stu, "student"); System.out.println(stu.hashCode()); System.out.println(map.get(stu)); stu.setAge(13); System.out.println(stu.hashCode()); System.out.println(map.get(stu)); } } @Data @AllArgsConstructor @NoArgsConstructor class Person { private String name; private Integer age; public int hashCode() { return 123456; } } @Data @AllArgsConstructor @NoArgsConstructor class Student { private String name; private Integer age; }
Résultat de sortie
123456person
123456
person
71 154
student
71213
null
Code source
hashCode code sourcepublic int hashCode() { int PRIME = true; int result = 1; Object $age = this.getAge(); int result = result * 59 + ($age == null ? 43 : $age.hashCode()); Object $name = this.getName(); result = result * 59 + ($name == null ? 43 : $name.hashCode()); return result; }map.get code source
/** * Returns the value to which the specified key is mapped, * or {@code null} if this map contains no mapping for the key. * * <p>More formally, if this map contains a mapping from a key * {@code k} to a value {@code v} such that {@code (key==null ? k==null : * key.equals(k))}, then this method returns {@code v}; otherwise * it returns {@code null}. (There can be at most one such mapping.) * * <p>A return value of {@code null} does not <i>necessarily</i> * indicate that the map contains no mapping for the key; it's also * possible that the map explicitly maps the key to {@code null}. * The {@link #containsKey containsKey} operation may be used to * distinguish these two cases. * * @see #put(Object, Object) */ public V get(Object key) { Node<K,V> e; return (e = getNode(hash(key), key)) == null ? null : e.value; } /** * Computes key.hashCode() and spreads (XORs) higher bits of hash * to lower. Because the table uses power-of-two masking, sets of * hashes that vary only in bits above the current mask will * always collide. (Among known examples are sets of Float keys * holding consecutive whole numbers in small tables.) So we * apply a transform that spreads the impact of higher bits * downward. There is a tradeoff between speed, utility, and * quality of bit-spreading. Because many common sets of hashes * are already reasonably distributed (so don't benefit from * spreading), and because we use trees to handle large sets of * collisions in bins, we just XOR some shifted bits in the * cheapest possible way to reduce systematic lossage, as well as * to incorporate impact of the highest bits that would otherwise * never be used in index calculations because of table bounds. */ static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); } /** * Implements Map.get and related methods * * @param hash hash for key * @param key the key * @return the node, or null if none */ final Node<K,V> getNode(int hash, Object key) { Node<K,V>[] tab; Node<K,V> first, e; int n; K k; if ((tab = table) != null && (n = tab.length) > 0 && (first = tab[(n - 1) & hash]) != null) { if (first.hash == hash && // always check first node ((k = first.key) == key || (key != null && key.equals(k)))) return first; if ((e = first.next) != null) { if (first instanceof TreeNode) return ((TreeNode<K,V>)first).getTreeNode(hash, key); do { if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) return e; } while ((e = e.next) != null); } } return null; }En brefVous pouvez voir qu'une table est obtenue en premier, qui est en fait un tableau. Recherchez ensuite la valeur correspondant à la clé dans le tableau. Le critère de recherche est que le hachage est égal au hachage du paramètre transmis et remplit l'une des deux autres conditions : k = e.key, ce qui signifie qu'il s'agit du même objet, ou de la clé de la cible égale. de la clé transmise. Notre problème réside dans le hash(key.hashCode()). Vous pouvez voir que HashMap hache le hashCode de la clé lors du stockage des éléments. Le hachage obtenu sera finalement utilisé comme base pour l'emplacement de stockage de l'élément. Correspondant à notre situation : lors du premier stockage, la fonction de hachage utilise key.hashCode comme paramètre pour obtenir une valeur, puis stocke l'élément dans un certain emplacement en fonction de cette valeur. Lorsque nous récupérons l'élément, la valeur de key.hashCode a changé, donc le résultat de la fonction de hachage ici a également changé, donc lorsqu'il essaie d'obtenir l'emplacement de stockage de cette clé, il ne peut pas obtenir la valeur correcte, ce qui en résulte. dans l'élément cible n'étant finalement pas trouvé. Pour le retourner correctement, c'est très simple. Changer la méthode hashCode de la classe Person pour que son hashCode ne dépende pas de l'attribut que l'on souhaite modifier. Cependant, cela ne doit pas être fait en développement réel. les attributs des deux objets sont différents, différentes valeurs de hashCode peuvent être renvoyées lorsqu'elles sont exactement les mêmes. La conclusion est donc qu'après avoir placé l'objet dans un HashMap, ne modifiez pas les attributs de la clé sauf si vous remplacez la méthode hashCode de la classe d'entité qui n'est pas soumise aux restrictions d'attributs.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!