A inclusão de um valor duplicado em um HashSet / HashMap substitui o valor anterior

Por favor, considere o seguinte pedaço de código:

HashSet hs = new HashSet(); hs.add("hi"); -- (1) hs.add("hi"); -- (2) 

hs.size() dará 1 como o HashSet não permite duplicatas, então apenas um elemento será armazenado.

Eu quero saber se adicionarmos o elemento duplicado, então ele substitui o elemento anterior ou simplesmente não o adiciona?

Além disso, o que acontecerá usando o HashMap para o mesmo caso?

No caso do HashMap , ele substitui o valor antigo pelo novo.

No caso do HashSet , o item não é inserido.

A primeira coisa que você precisa saber é que o HashSet age como um Set , o que significa que você adiciona seu object diretamente ao HashSet e não pode conter duplicatas. Você acabou de adicionar seu valor diretamente no HashSet .

No entanto, o HashMap é um tipo de Map . Isso significa que, toda vez que você adicionar uma input, você adicionará um par de valores-chave.

No HashMap você pode ter valores duplicados, mas não chaves duplicadas. No HashMap a nova input replaceá a antiga. A input mais recente estará no HashMap .

Entendendo o link entre o HashMap e o HashSet:

Lembre-se, o HashMap não pode ter chaves duplicadas. Por trás da cena, o HashSet usa um HashMap .

Quando você tenta include qualquer object em um HashSet , essa input é, na verdade, armazenada como uma chave no HashMap – o mesmo HashMap usado atrás da cena do HashSet . Como esse HashMap subjacente precisa de um par de valores-chave, um valor fictício é gerado para nós.

Agora, quando você tenta inserir outro object duplicado no mesmo HashSet , ele tentará novamente inseri-lo como uma chave no HashMap localizado embaixo. No entanto, o HashMap não suporta duplicatas. Portanto, o HashSet ainda resultará em apenas um valor desse tipo. Como uma nota lateral, para cada chave duplicada, desde que o valor gerado para nossa input no HashSet é algum valor random / dummy, a chave não é substituída de todo. ele será ignorado, já que remover a chave e adicionar a mesma chave (o valor fictício é o mesmo) não faria qualquer sentido.

Resumo:

HashMap permite values duplicados, mas não keys . HashSet não pode conter duplicados.

Para saber se a adição de um object foi concluída com êxito ou não, você pode verificar o valor boolean retornado ao chamar .add() e ver se ele retorna true ou false . Se retornou true , foi inserido.

Os documentos são bem claros: o HashSet.add não substitui:

Adiciona o elemento especificado a este conjunto, se ainda não estiver presente. Mais formalmente, adiciona o elemento especificado e a este conjunto se este conjunto não contiver nenhum elemento e2 tal que (e == null? E2 == null: e.equals (e2)). Se esse conjunto já contiver o elemento, a chamada deixará o conjunto inalterado e retornará falso.

Mas o HashMap.put replaceá:

Se o mapa continha anteriormente um mapeamento para a chave, o valor antigo é substituído.

É o caso do HashSet, NÃO o substitui.

Dos docs:

http://docs.oracle.com/javase/6/docs/api/java/util/HashSet.html#add(E )

“Adiciona o elemento especificado a este conjunto se ainda não estiver presente. Mais formalmente, adiciona o elemento especificado e a este conjunto se este conjunto não contiver nenhum elemento e2 tal que (e == null? E2 == null: e.equals ( e2)). Se este conjunto já contém o elemento, a chamada deixa o conjunto inalterado e retorna falso. ”

Corrija-me se estiver errado, mas o que você está percebendo é que, com strings, “Hi” == “Hi” nem sempre é verdadeiro (porque não são necessariamente o mesmo object).

O motivo pelo qual você está obtendo uma resposta de 1 é porque a JVM reutilizará objects de strings sempre que possível. Nesse caso, a JVM está reutilizando o object de cadeia de caracteres e, portanto, sobrescrevendo o item no Hashmap / Hashset.

Mas você não tem a garantia desse comportamento (porque pode ser um object de string diferente que tenha o mesmo valor “Hi”). O comportamento que você vê é apenas devido à otimização da JVM.

Você precisa verificar o método put no mapa Hash primeiro, já que o backup do HashSet é feito pelo HashMap

  1. Quando você adiciona um valor duplicado, diga uma String “One” no HashSet,
  2. Uma input (“one”, PRESENT) será inserida no Hashmap (para todos os valores adicionados em set, o valor será “PRESENT”, que se for do tipo Object)
  3. Hashmap adiciona a input no Mapa e retorna o valor, que neste caso é “PRESENT” ou nulo se Entrada não estiver lá.
  4. O método add de Hashset então retorna true se o valor retornado de Hashmap for igual a null caso contrário false, o que significa que uma input já existe …

Para dizer de forma diferente: Quando você insere um par de valores-chave em um HashMap onde a chave já existe (em certo sentido, hashvalue () fornece o mesmo valor und equal () é true, mas os dois objects ainda podem diferir de várias maneiras ), a chave não é substituída, mas o valor é sobrescrito. A chave é usada apenas para obter o hashvalue () e encontrar o valor na tabela com ele. Como o HashSet usa as chaves de um HashMap e define valores arbitrários que realmente não importam (para o usuário), os Elementos do Conjunto também não são substituídos.

HashMap contém basicamente Entry que subseqüentemente contém keys (Object) e Value (Object). Internamente HashSet são HashMap e HashMap do substitui valores como alguns de vocês já apontaram..mas isso realmente substitui as chaves ??? Não ..e isso é O truque aqui.HashMap mantém seu valor como chave no HashMap subjacente e valor é apenas um object fictício.Então, se você tentar reinserir o mesmo valor no HashMap (chave no mapa subjacente). Ele apenas substitui o valor fictício e não a chave ( Valor para HashSet).

Veja o código abaixo para HashSet Class:

public boolean [Mais …] adicionar (Ee) {

  return map.put(e, PRESENT)==null; } 

Aqui e é o valor para HashSet, mas a chave para o mapa subjacente.e a chave nunca é substituída. Espero que eu possa limpar a confusão.