Должен ли я вернуть объект, а затем добавить новый? Или я могу просто увеличивать?
Integer temp = myMap.get(key);
temp++;
myMap.put(key, temp);
нет способа сделать это (это не работает):
myMap.get(key)++;
Должен ли я вернуть объект, а затем добавить новый? Или я могу просто увеличивать?
Integer temp = myMap.get(key);
temp++;
myMap.put(key, temp);
нет способа сделать это (это не работает):
myMap.get(key)++;
Должен ли я вернуть объект, а затем добавить новый?
Пока вы используете класс оболочки Integer
yes, потому что он неизменен. Вместо этого вы можете использовать изменяемый класс-оболочку, даже тот, который имеет метод increment()
. Однако вы теряете возможность использовать autoboxing и autounboxing для значений.
Вы можете использовать переменное целое число, такое как AtomicInteger.
Map<Key, AtomicInteger> myMap = new HashMap<Key, AtomicInteger>();
myMap.get(key).incrementAndGet();
Или вы можете использовать Trove4j, который поддерживает примитивы в коллекциях.
TObjectIntHashMap<Key> myMap;
myMap.increment(key);
Это самый короткий код, который выполняет эту работу.
myMap.put(key, myMap.get(key) + 1)
Я думаю, что это не слишком долго.
В Java 8 на Map
есть новые методы, которые вы можете использовать с lambdas для решения этой проблемы. Первая альтернатива, compute
:
a.compute(key, (k, v) -> v+1);
Обратите внимание, что это работает, только если хэш инициализирован для всех возможных ключей.
Если это не гарантировано, вы можете либо изменить приведенный выше код на:
a.compute(key, (k, v) -> v == null ? 1 : v + 1);
Или используйте метод merge
(который я бы предпочел):
a.merge(key, 1, (a, b) -> a + b);
Возможно, есть больше методов на основе лямбда, о которых я не знаю.
Вы не можете напрямую увеличить его, потому что это immutable. Вы должны увеличить его и вернуть новый объект.
Здесь также вмешивается автоматический бокс. На самом деле то, что происходит, похоже на:
Integer i1 = getFromMap();
i1 = Integer.valueOf(++ i1.intValue());
Итак, здесь ваша ссылка указывает на новый объект. Вы должны вернуть этот объект на карту под тем же ключом.
Поскольку Integer
неизменяемы, да, вы должны сделать это таким образом.
Если вы действительно хотите увеличить его напрямую, вам придется написать свой собственный изменяемый класс.
Если вам нужно сделать это более двух раз, вы предпочтете создать крошечный класс, например:
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();
}
}
Прежде всего: будьте в курсе unboxing: temp от типа Integer. Но операция ++ реализована для int. Поэтому temp распаковывается для ввода int. Это означает, что если temp null, вы выполняете исключение NullPointerException.
И вы должны сделать это, как вы записали в свой первый блок кода.
Я использую приведенный ниже код, и он работает, но вначале вам нужно определить BiFunction
, описывающий, что операция увеличивается на 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"));
}
вывод
3
1
Просто для полноты в Java 8 существует longAdder, который приносит некоторые преимущества по сравнению с 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();
Это должно работать
// If the key you want to add does not exist then add it as a new key
// And make the value 1
if (map.get(key) == null) {
map.put(key, 1);
} else {
// If the key does exist then replace the key value with it's
// Original value plus one
map.put(key, map.get(key) + 1);
}