Dois-je retourner l'objet et ensuite en mettre un nouveau? Ou puis-je simplement incrémenter directement?
Integer temp = myMap.get(key);
temp++;
myMap.put(key, temp);
il n'y a pas moyen de faire ça (ça ne marche pas):
myMap.get(key)++;
Dois-je retourner l'objet et ensuite en mettre un nouveau?
Tant que vous utilisez la classe wrapper Integer
, oui, car elle est immuable. Vous pouvez utiliser une classe wrapper mutable à la place, même avec une méthode increment()
. Cependant, vous perdez alors la possibilité d'utiliser la sélection automatique et la boîte automatique sur les valeurs.
C'est le code le plus court qui fait ce travail.
myMap.put(key, myMap.get(key) + 1)
Je pense que ce n'est pas trop long.
Vous pouvez utiliser un entier mutable tel que AtomicInteger.
Map<Key, AtomicInteger> myMap = new HashMap<Key, AtomicInteger>();
myMap.get(key).incrementAndGet();
Ou vous pouvez utiliser Trove4j qui prend en charge les primitives dans les collections.
TObjectIntHashMap<Key> myMap;
myMap.increment(key);
Dans Java 8, il existe de nouvelles méthodes sur Map
que vous pouvez utiliser avec lambdas pour résoudre ce problème. Première alternative, compute
:
a.compute(key, (k, v) -> v+1);
Notez que cela ne fonctionne que si le hachage est initialisé pour toutes les clés possibles.
Si cela n'est pas garanti, vous pouvez soit changer le code ci-dessus en:
a.compute(key, (k, v) -> v == null ? 1 : v + 1);
Ou utilisez la méthode merge
(que je préférerais):
a.merge(key, 1, (a, b) -> a + b);
Peut-être n’y at-il pas d’autres méthodes basées sur Lambda que je ne connais pas.
Vous ne pouvez pas l'incrémenter directement car il est immuable . Vous devez l'incrémenter et remettre le nouvel objet.
La boxe automatique est également interférer ici. En fait, ce qui se passe est quelque chose de similaire à:
Integer i1 = getFromMap();
i1 = Integer.valueOf(++ i1.intValue());
Alors voici vos points de référence vers un nouvel objet. Vous devez replacer cet objet sur la carte, sous la même clé.
Comme Integer
sont immuables, oui, vous devez le faire de cette façon . Si vous voulez vraiment l'incrémenter directement, vous devrez écrire votre propre classe mutable.
Si vous devez le faire plus de deux fois, vous préférez créer une classe minuscule comme:
public class MappedCounter {
private Map<String, Integer> map = new HashMap<String, Integer>();
public void addInt(String k, int v) {
if (!map.containsKey(k)) map.put(k, v);
else map.put(k, map.get(k) + v);
}
public int getInt(String k) {
return map.containsKey(k) ? map.get(k) : 0;
}
public Set<String> getKeys() {
return map.keySet();
}
}
Pour être complet, Java 8 contient un longAdder qui présente certains avantages par rapport à AtomicInteger ( http://docs.Oracle.com/javase/8/docs/api/Java/util/concurrent/atomic/LongAdder.html )
final Map<WhatEver, LongAdder> result = new HashMap<>();
result.get(WhatEver).increment();
Tout d’abord: soyez conscient du déballage: le temp est de type Integer. Mais l'opération ++ est implémentée pour int. Donc temp est décaissé pour taper int. Cela signifie que si temp est null, vous exécutez une exception NullPointerException.
Et vous devez le faire comme vous l'avez décrit dans votre premier bloc de code.
J'utilise le code ci-dessous et cela fonctionne, mais au début, vous devez définir un BiFunction
décrivant que l'opération est incrémentée de 1.
public static Map<String, Integer> strInt = new HashMap<String, Integer>();
public static void main(String[] args) {
BiFunction<Integer, Integer, Integer> bi = (x,y) -> {
if(x == null)
return y;
return x+y;
};
strInt.put("abc", 0);
strInt.merge("abc", 1, bi);
strInt.merge("abc", 1, bi);
strInt.merge("abc", 1, bi);
strInt.merge("abcd", 1, bi);
System.out.println(strInt.get("abc"));
System.out.println(strInt.get("abcd"));
}
la sortie est
3
1