Forse sto lavorando troppo e forse mi sto perdendo in un bel bicchiere d'acqua, ma questo comportamento da parte del metodo containsKey() di HashMap non me lo riesco a spiegare.

Vediamo la situazione. Ho costruito la seguente classe, che intendo usare come chiave all'interno della HashMap:
codice:
public class KeyDay implements Comparable {
   private String id;
   private String internalID;

   public KeyDay(String id) {
      this.id = id;
      createInternalID();
   }

   private void createInternalID() {
      internalID = id.substring(6, 10) + id.substring(3, 5) + id.substring(0, 2);
   }

   public String getInternalID() { return internalID; }
   public String toString() { return id; }

   public int compareTo(Object obj) {
      KeyDay k = (KeyDay) obj;
      return internalID.compareTo( k.getInternalID() );
   }

   public boolean equals(Object obj) {
      KeyDay kd = (KeyDay) obj;
      return internalID.equals( kd.getInternalID() );
   }

   public static void main(String[] args) {
      KeyDay k1 = new KeyDay("12/05/2008");
      KeyDay k2 = new KeyDay("12/05/2008");
      System.out.println("Equals: " + k1.equals(k2) + " -- " + k2.equals(k1));
      System.out.println("CompareTo: " + k1.compareTo(k2) + " -- " + k2.compareTo(k1));
   }
}
Il main l'ho aggiunto solo a scopo di test, per verificare che la classe abbia il comportamento che desidero, ed in fatti così è... questo è il suo output:
codice:
Equals: true -- true
CompareTo: 0 -- 0
Eppure, appena tento di utilizzare questa classe in una HashMap, il comportamento non è coerente con quanto imposto dal metodo equals() da me ridefinito. Questo è l'esempio:
codice:
import java.util.*;

public class Tester {
   public static void main(String[] args) {
      // Questi saranno i miei valori chiave
      String[] date = {"12/05/2008", "12/05/2008", "12/05/2008"};

      HashMap hm = new HashMap();
      for(int i=0; i<date.length; i++) {
         KeyDay day = new KeyDay( date[i] );
         if ( hm.containsKey(day) ) {
            System.out.println("Trovata la data nel calderone");
         } else {
            System.out.println("Data " + day + " non trovata nel calderone... la inserisco");
            hm.put(day, "Inserita");
         }
      }

      Iterator it = hm.keySet().iterator();
      while( it.hasNext() ) System.out.println( it.next() );
   }
}
L'esempio è stupido, ma questo è il suo output:
codice:
Data 12/05/2008 non trovata nel calderone... la inserisco
Data 12/05/2008 non trovata nel calderone... la inserisco
Data 12/05/2008 non trovata nel calderone... la inserisco
12/05/2008
12/05/2008
12/05/2008
Ora, stando alla documentazione del metodo containsKey() dell'interfaccia Map (la documentazione di HashMap dice che tale metodo è specificato all'interno di tale interfaccia, dato che la implementa)
Returns true if this map contains a mapping for the specified key. More formally, returns true if and only if this map contains at a mapping for a key k such that (key==null ? k==null : key.equals(k)). (There can be at most one such mapping.)
La chiave non è nulla, quindi il valore restituito dovrebbe essere quello di
codice:
key.equals(k)
che per la definizione precedente (vedi esecuzione della classe KeyDay) è coerente...

Allora mi domando: dove sto sbagliando?


Ciao.