web-dev-qa-db-fra.com

Incrémenter un entier dans une carte de hachage

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)++;
27
NimChimpsky

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.

13
Michael Borgwardt

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.

21
AlexR

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); 
20
Peter Lawrey

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. 

17
Jonathan Heinen

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é.

7
Bozho

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.

3
Nicolas

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();
    }
}
2
leonbloy

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();
0
Markus Schreiber

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.

0
scheffield

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
0
MGoksu