Suponha que tenhamos um HashMap<String, Integer>
em Java.
Como atualizo (incremento) o valor inteiro da chave de cadeia para cada existência da cadeia que encontro?
Pode-se remover e reinserir o par, mas a sobrecarga seria uma preocupação.
Outra maneira seria colocar o novo par e o antigo seria substituído.
Neste último caso, o que acontece se houver uma colisão de código de hash com uma nova chave que estou tentando inserir? O comportamento correto para uma hashtable seria atribuir um local diferente para ele ou fazer uma lista dele no intervalo atual.
getOrDefault
, por exemplo:map.put(key, count.getOrDefault(key, 0) + 1);
Maneira Java 8:
Você pode usar o
computeIfPresent
método e fornecer a ele uma função de mapeamento, que será chamada para calcular um novo valor com base no valor existente.Por exemplo,
Como alternativa, você pode usar o
merge
método, em que 1 é o valor padrão e a função incrementa o valor existente em 1:Além disso, há um conjunto de outros métodos úteis, tais como
putIfAbsent
,getOrDefault
,forEach
, etc.fonte
null
(digamoswords.put("hello", null);
), o resultado aindanull
não é o1
que eu esperaria.compute()
, em vez disso, ele manipularánull
valores também..merge
É a minha solução comInteger::sum
.O método
put
irá substituir o valor de uma chave existente e criará-lo se não existe.fonte
nullPointer Exception
.null + 1
pois isso tentará descompactar o arquivonull
em um número inteiro para fazer o incremento.A maneira simplificada do Java 8 :
Isso usa o método do HashMap que recupera o valor de uma chave, mas se a chave não puder ser recuperada, ela retornará o valor padrão especificado (neste caso, um '0').
Isso é suportado no Java principal: HashMap <K, V> getOrDefault (Chave do objeto, V defaultValue)
fonte
Substitua
Integer
porAtomicInteger
e chame um dos métodosincrementAndGet
/getAndIncrement
nele.Uma alternativa é agrupar uma classe
int
em sua própriaMutableInteger
classe que possua umincrement()
método, você só tem uma preocupação de segurança de thread a resolver ainda.fonte
MutableInteger
é melhor, comoAtomicInteger
usosvolatile
, que tem sobrecarga. Eu usaria emint[1]
vez deMutableInteger
.Solução de uma linha:
fonte
@ A solução de Matthew é a mais simples e terá bom desempenho na maioria dos casos.
Se você precisar de alto desempenho, o AtomicInteger é uma solução melhor, ala @BalusC.
No entanto, uma solução mais rápida (desde que a segurança do encadeamento não seja um problema) é usar TObjectIntHashMap, que fornece um método de incremento (chave) e usa primitivos e menos objetos do que a criação de AtomicIntegers. por exemplo
fonte
Você pode incrementar como abaixo, mas precisa verificar a existência para que uma NullPointerException não seja lançada
fonte
O hash existe (com 0 como valor) ou é "colocado" no mapa no primeiro incremento? Se for "colocado" no primeiro incremento, o código deve se parecer com:
fonte
Pode ser um pouco tarde, mas aqui estão meus dois centavos.
Se você estiver usando o Java 8, poderá usar o método computeIfPresent . Se o valor da chave especificada estiver presente e não for nulo, ele tentará calcular um novo mapeamento, dada a chave e seu valor mapeado atual.
Também podemos fazer uso de outro método putIfAbsent para colocar uma chave. Se a chave especificada ainda não estiver associada a um valor (ou estiver mapeada para nula), esse método a associará ao valor fornecido e retornará nulo; caso contrário, retornará o valor atual.
No caso do mapa é compartilhado entre threads, então podemos fazer uso de
ConcurrentHashMap
e AtomicInteger . Do documento:Podemos usá-los como mostrado:
Um ponto a observar é que estamos invocando
get
para obter o valor da chaveB
e, em seguida, invocandoincrementAndGet()
seu valor, que é claroAtomicInteger
. Podemos otimizá-lo, pois o métodoputIfAbsent
retorna o valor da chave, se já estiver presente:Além disso, se planejarmos usar o AtomicLong , conforme a documentação sob alta contenção, a taxa de transferência esperada do LongAdder será significativamente maior, à custa de um maior consumo de espaço. Verifique também esta pergunta .
fonte
A solução mais limpa sem NullPointerException é:
fonte
Como não posso comentar algumas respostas devido à menor reputação, publicarei uma solução que apliquei.
fonte
Use um
for
loop para incrementar o índice:fonte
Há respostas enganosas para esta pergunta aqui que implicam que o método put Hashtable substituirá o valor existente se a chave existir; isso não é verdade para o Hashtable, mas para o HashMap. Consulte Javadoc para HashMap http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29
fonte
ou
Inteiro é tipos de dados primitivos http://cs.fit.edu/~ryan/java/language/java-data.html , então você precisa removê-lo, fazer algum processo e colocá-lo novamente. se você tiver um valor que não seja do tipo Primitivo, precisará retirá-lo, processá-lo e não precisará colocá-lo novamente no mapa de hash.
fonte
Tentar:
NOTA:
Você pode alterar a chave ou o valor no seu hashmap, mas não pode alterar as duas ao mesmo tempo.
fonte
Use Java8 construído em função 'computeIfPresent'
Exemplo:
fonte