Se eu passar a mesma chave várias vezes para HashMap
o put
método, o que acontece com o valor original? E se o valor se repetir? Não encontrei nenhuma documentação sobre isso.
Caso 1: Valores sobrescritos para uma chave
Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
System.out.println(mymap.get("1"));
Nós recebemos surely not one
.
Caso 2: valor duplicado
Map mymap = new HashMap();
mymap.put("1","one");
mymap.put("1","not one");
mymap.put("1","surely not one");
// The following line was added:
mymap.put("1","one");
System.out.println(mymap.get("1"));
Nós recebemos one
.
Mas o que acontece com os outros valores? Eu estava ensinando básico a um aluno e me perguntaram isso. É Map
como um balde em que o último valor é referenciado (mas na memória)?
Respostas:
Por definição, o
put
comando substitui o valor anterior associado à chave fornecida no mapa (conceitualmente como uma operação de indexação de matriz para tipos primitivos).O mapa simplesmente elimina sua referência ao valor. Se nada mais contiver uma referência ao objeto, esse objeto se tornará elegível para a coleta de lixo. Além disso, Java retorna qualquer valor anterior associado à chave fornecida (ou
null
se não houver nenhum), para que você possa determinar o que estava lá e manter uma referência, se necessário.Mais informações aqui: HashMap Doc
fonte
Você pode encontrar sua resposta no javadoc do Mapa # put (K, V) (que realmente retorna algo):
Portanto, se você não atribuir o valor retornado ao chamar
mymap.put("1", "a string")
, ele se tornará não referenciado e, portanto, elegível para a coleta de lixo.fonte
null
), conforme documentado logo acima no javadoc, portanto, sim, é isso que eu quero dizer. Pode realmente ser mal interpretado?O valor anterior da chave é descartado e substituído pelo novo.
Se você deseja manter todos os valores fornecidos por uma chave, considere implementar algo como isto:
fonte
é o recurso Chave / Valor e você não pode ter uma chave duplicada para vários valores, porque quando você deseja obter o valor real de qual um dos valores pertence à chave inserida
no seu exemplo, quando deseja obter o valor "1", qual é isto ?!
é por isso que temos uma chave exclusiva para cada valor, mas você pode ter um truque usando a java standard lib:
e você poderia usá-lo desta maneira:
e o resultado das impressões são:
fonte
Associa o valor especificado à chave especificada neste mapa. Se o mapa continha anteriormente um mapeamento para a chave, o valor antigo será substituído.
fonte
Ele substitui o valor existente no mapa pela respectiva chave. E se nenhuma chave existir com o mesmo nome, ela criará uma chave com o valor fornecido. por exemplo:
Tecla OUTPUT = "1", valor = "dois"
Portanto, o valor anterior é substituído.
fonte
Para sua pergunta se o mapa era como um balde: não.
É como uma lista com
name=value
pares, emboraname
não precise ser uma String (pode).Para obter um elemento, você passa sua chave para o método get () - que fornece o objeto atribuído em troca.
E um mapa Hash significa que, se você estiver tentando recuperar seu objeto usando o método get, ele não comparará o objeto real com o que você forneceu, porque precisaria percorrer sua lista e comparar () a chave você forneceu o elemento atual.
Isso seria ineficiente. Em vez disso, não importa em que consiste seu objeto, ele calcula o chamado código hash dos dois objetos e os compara. É mais fácil comparar dois
int
s em vez de dois objetos inteiros (possivelmente profundamente complexos). Você pode imaginar o código de hash como um resumo com um comprimento predefinido (int); portanto, ele não é único e possui colisões. Você encontra as regras para o hashcode na documentação na qual inseri o link.Se você quiser saber mais sobre isso, consulte os artigos em javapractices.com e technofundo.com
Saudações
fonte
Eu sempre usei:
se eu quisesse aplicar várias coisas a uma chave de identificação.
você sempre pode fazer algo assim e criar um labirinto!
fonte
Os mapas do JDK não se destinam ao armazenamento de dados sob chaves duplicadas.
Na melhor das hipóteses, o novo valor substituirá os anteriores.
O pior cenário é a exceção (por exemplo, quando você tenta coletá-lo como um fluxo):
Sem duplicatas:
Stream.of("one").collect(Collectors.toMap(x -> x, x -> x))
Fluxo duplicado:
Stream.of("one", "not one", "surely not one").collect(Collectors.toMap(x -> 1, x -> x))
Para lidar com chaves duplicadas - use outro pacote, por exemplo: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/collect/Multimap.html
Existem muitas outras implementações que lidam com chaves duplicadas. Eles são necessários para a web (por exemplo, chaves de cookies duplicadas, cabeçalhos de HTTP podem ter os mesmos campos, ...)
Boa sorte! :)
fonte
Collectors.toMap()
possui o terceiro argumento - função de mesclagem. Se queremos simplesmente substituir último elemento duplicado:Stream.of("one", "two", "one").collect(Collectors.toMap(x -> x, x -> x, (key1, key2) -> key2))
. link"one", "not one", "surely not one"
não produzirá nenhum erro de chave duplicado devido a todas as strings diferentes.BTW, se você quiser alguma semântica, como colocar apenas se essa chave não existir. você pode usar
concurrentHashMap
com aputIfAbsent()
função Veja isso:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html#put(K,%20V)
concurrentHashMap
é seguro para threads com alto desempenho, pois usa o mecanismo de " bloqueio de distribuição " para melhorar a taxa de transferência.fonte
Sim, isso significa que todas as 1 chaves com valor são substituídas pelo último valor adicionado e aqui você adiciona "certamente não uma", para exibir apenas "certamente não uma".
Mesmo se você estiver tentando exibir com um loop, ele também exibirá apenas uma chave e valor com a mesma chave.
fonte
Significa que o mapa de hash não permitirá duplicatas, se você tiver substituído corretamente os métodos equals e hashCode ().
O HashSet também usa o HashMap internamente, consulte o documento de origem
fonte