Supongamos que tenemos un HashMap<String, Integer>
en Java.
¿Cómo actualizo (incremento) el valor entero de la cadena-clave para cada existencia de la cadena que encuentro?
Uno podría quitar y volver a entrar en el par, pero los gastos generales serían una preocupación.
Otra forma sería simplemente poner el nuevo par y el viejo sería reemplazado.
En el último caso, ¿qué sucede si hay una colisión de código hash con una nueva clave que estoy tratando de insertar? El comportamiento correcto para una tabla hash sería asignarle un lugar diferente o hacer una lista en el depósito actual.
getOrDefault
, por ejemplo:map.put(key, count.getOrDefault(key, 0) + 1);
Manera Java 8:
Puede usar el
computeIfPresent
método y proporcionarle una función de mapeo, que se llamará para calcular un nuevo valor basado en uno existente.Por ejemplo,
Alternativamente, puede usar el
merge
método, donde 1 es el valor predeterminado y la función incrementa el valor existente en 1:Además, hay un montón de otros métodos útiles, tales como
putIfAbsent
,getOrDefault
,forEach
, etc.fuente
null
(digamoswords.put("hello", null);
), el resultado aúnnull
no1
es el que esperaría.compute()
en su lugar, también manejaránull
valores..merge
es mi solución conInteger::sum
.El método
put
se reemplace el valor de una clave existente y se creará si no existe.fuente
nullPointer Exception
.null + 1
ya que esto intentará desempaquetarnull
en un entero para hacer el incremento.La forma simplificada de Java 8 :
Esto utiliza el método de HashMap que recupera el valor de una clave, pero si la clave no se puede recuperar, devuelve el valor predeterminado especificado (en este caso, un '0').
Esto es compatible con Java central: HashMap <K, V> getOrDefault (clave de objeto, V defaultValue)
fuente
Reemplace
Integer
porAtomicInteger
y llame a uno de los métodosincrementAndGet
/getAndIncrement
en él.Una alternativa es envolver un
int
en su propiaMutableInteger
clase que tiene unincrement()
método, solo tiene una preocupación de seguridad de hilos para resolver todavía.fuente
MutableInteger
es mejor, comoAtomicInteger
usosvolatile
, que tiene gastos generales. Yo usaría enint[1]
lugar deMutableInteger
.Solución de una línea:
fuente
La solución de @ Matthew es la más simple y funcionará lo suficientemente bien en la mayoría de los casos.
Si necesita un alto rendimiento, AtomicInteger es una mejor solución ala @BalusC.
Sin embargo, una solución más rápida (siempre que la seguridad de los hilos no sea un problema) es usar TObjectIntHashMap, que proporciona un método de incremento (clave) y usa primitivas y menos objetos que crear AtomicIntegers. p.ej
fuente
Puede aumentar como a continuación, pero debe verificar la existencia para que no se produzca una NullPointerException
fuente
¿Existe el hash (con 0 como valor) o se "pone" en el mapa en el primer incremento? Si se "pone" en el primer incremento, el código debería verse así:
fuente
Puede que sea un poco tarde, pero aquí están mis dos centavos.
Si está utilizando Java 8, puede utilizar el método computeIfPresent . Si el valor para la clave especificada está presente y no es nulo, entonces intenta calcular una nueva asignación dada la clave y su valor asignado actual.
También podemos hacer uso de otro método putIfAbsent para poner una clave. Si la clave especificada no está ya asociada a un valor (o está asignada a nulo), este método la asocia al valor dado y devuelve nulo; de lo contrario, devuelve el valor actual.
En caso de que el mapa se comparte a través de las discusiones a continuación, podemos hacer uso de
ConcurrentHashMap
y AtomicInteger . Del documento:Podemos usarlos como se muestra:
Un punto a tener en cuenta es que estamos invocando
get
para obtener el valor de la claveB
y luego invocandoincrementAndGet()
su valor, que es, por supuestoAtomicInteger
. Podemos optimizarlo ya que el métodoputIfAbsent
devuelve el valor de la clave si ya está presente:En una nota al margen si planeamos usar AtomicLong, entonces, según la documentación bajo alta contención, el rendimiento esperado de LongAdder es significativamente mayor, a expensas de un mayor consumo de espacio. También revise esta pregunta .
fuente
La solución más limpia sin NullPointerException es:
fuente
Como no puedo comentar algunas respuestas debido a la menor reputación, publicaré una solución que apliqué.
fuente
Use un
for
bucle para incrementar el índice:fuente
Aquí hay respuestas engañosas a esta pregunta que implican que el método de colocación Hashtable reemplazará el valor existente si la clave existe, esto no es cierto para Hashtable sino para HashMap. Consulte Javadoc para HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29
fuente
o
Entero son tipos de datos primitivos http://cs.fit.edu/~ryan/java/language/java-data.html , por lo que debe extraerlo, realizar algún proceso y luego volver a colocarlo. Si tiene un valor que no son tipos de datos primitivos, solo necesita extraerlo, procesarlo, no es necesario volver a colocarlo en el hashmap.
fuente
Tratar:
NOTA:
Puede cambiar la clave o el valor en su hashmap, pero no puede cambiar ambos al mismo tiempo.
fuente
Utilice Java8 integrado en la función 'computeIfPresent'
Ejemplo:
fuente