Duvida HashSet

Question 174
Click the Exhibit button.

import java.util.*;
class KeyMaster {
   public int i;
   public KeyMaster(int i) { this.i = i; }
   public boolean equals(Object o) { return i == ((KeyMaster)o).i; }
   public int hashCode() { return i; }
}
public class MapIt {
   public static void main(String[] args) {
      Set<KeyMaster> set = new HashSet<KeyMaster>();
      KeyMaster k1 = new KeyMaster(1);
      KeyMaster k2 = new KeyMaster(2);
      set.add(k1); set.add(k1);
      set.add(k2); set.add(k2);
      System.out.print(set.size() + ?:?);
      k2.i = 1;
      System.out.print(set.size() + ?:?);
      set.remove(k1);
      System.out.print(set.size() + ?:?);
      set.remove(k2);
      System.out.print(set.size());
   }
}[/code]

What is the result?
A. 4:4:2:2
B. 4:4:3:2
C. 2:2:1:0
D. 2:2:0:0
E. 2:1:0:0
F. 2:2:1:1
G. 4:3:2:1

Answer: F

Alguem poderia me explicar o porque de F?

para mim a resposta seria a C.

Valeu

Bem… esse é o tipo de coisa que duvido que caia numa prova, pois é uma questão mal escrita e mal intencionada.

Você não pode alterar o valor retornado pelo hashCode de um objeto, depois dele estar adicionado num HashSet ou ser chave de um HashMap. O mapa se perde e o comportamento torna-se indefinido. O resultado exato pode variar de implementação para implementação.

Analisemos:

[code]
public static void main(String[] args) {
Set<KeyMaster> set = new HashSet<KeyMaster>();
KeyMaster k1 = new KeyMaster(1);
KeyMaster k2 = new KeyMaster(2);

  //Aqui, adicionou-se 2 vezes o k1. 
  //O set, por definição nos garante que k1 só será adicionado 1 vez, já que ambos tem o mesmo hashcode.
  set.add(k1); set.add(k1);   

  //O mesmo comentário acima vale para o k2
  set.add(k2); set.add(k2);   

  //Não surpreendente: retorna 2.
  System.out.print(set.size() + ":");   
  //Aqui vem a bobagem... o usuário alterou o valor de i e, portanto, o hashcode também.
  //O objeto não vai notificar o hashSet da mudança. Portanto, temos um k2 com hashCode 1 no 
  //local do hashCode 2. O set não vai magicamente saber dessa mudança.
  k2.i = 1;   

  //Como nada no set mudou (nenhum add ou remove chamado), o tamanho continua o mesmo: 2
  System.out.print(set.size() + ":");   

  //Agora pedimos para remover k1. O código vai até a posição de k1 e o remove. Ok.
  set.remove(k1);   

  //Tamanho 1. k1 foi removido.
  System.out.print(set.size() + ":");   

  //Pedimos para remover k2. Agora o set vai até a posição de??? k1. 
  //Pois o hashcode de k2 agora é um, graças a linha k2.i = 1. Não há nada para remover lá.
  set.remove(k2);   

  //O tamanho permanece 1.
  System.out.print(set.size());   

} [/code]

Otima explicação.

Muito obrigado ViniGodoy

Putz, agora entendi porque estava dando erro no sistema.

Valeu!!