title: Why containsKey() of Map only invoke hashCode()?
body: <p>I read interface Map's JavaDoc and it says this:</p>
  
  <blockquote>
    <p>Many methods in Collections Framework interfaces are defined in terms of the equals
    method. For example, the specification for the <code>containsKey(Object key)</code> method says: 
    "returns true if and only if this map contains a mapping for a key <code>k</code> such that 
    <code>(key==null ? k==null : key.equals(k))</code>." This specification should not be construed 
    to imply that invoking <code>Map.containsKey</code> with a non-<code>null</code> argument <code>key</code> will 
    cause <code>key.equals(k)</code> to be invoked for any key <code>k</code>. Implementations are free to 
    implement optimizations whereby the <code>equals</code> invocation is avoided, 
    for example, by first comparing the hash codes of the two keys. 
    (The <code>Object.hashCode()</code> specification guarantees that two objects with unequal 
    hash codes cannot be equal.)</p>
  </blockquote>
  
  <p>My understanding is when <code>containsKey()</code> is invoked, both hashCode() and equals() wil be called, therefore I wrote my own code to test it.</p>
  
  <p>HappyDay class will be stored as a key in HashMap, I override hashCode() and equals() methods, and add <code>System.out.println("invoking hashCode()" + this.happyHour);</code> and <code>System.out.println("invoking equals()");</code> to check whether the method is invoked or not.</p>
  
  <pre><code>public class HappyDay {
  
      private final int happyHour;
  
      public HappyDay(int hh) {
          this.happyHour = hh;
      }
  
      public int getHappyHour() {
          return this.happyHour;
      }
  
      @Override
      public boolean equals(Object o) {
          System.out.println("invoking equals()");
          if (o == null) {return false;}
  
          if (o == this) {return true;}
  
          //this is an easy overridden, if happy hour equal, objects will be equal.
          if (o instanceof HappyDay) {
              HappyDay other = (HappyDay) o;
              int otherHappyHour = other.getHappyHour();
              if (this.happyHour == otherHappyHour) {
                  return true;
              }
          }
          return false;
      }
  
      @Override
      public int hashCode() {
          System.out.println("invoking hashCode()" + this.happyHour);
          int hash = 7;
          hash = hash + this.happyHour;
          return hash;
      }
  }
  
  public class Main {
      public static void main(String[] args) {
          Map&lt;HappyDay,String&gt; hm = new HashMap&lt;&gt;();
  
          HappyDay hd1 = new HappyDay(1);
          HappyDay hd2 = new HappyDay(2);
  
          hm.put(hd1, "hd1");
          hm.put(hd2, "hd2");
  
          if(hm.containsKey(hd2)){
              System.out.println("found");
          }else{
              System.out.println("not exist");
          }
      }
  }
  </code></pre>
  
  <p>The Main class is to put two HappyDay instances into HashMap, after insertion(put() method), I invoke <code>hm.containsKey(hd2)</code>, as I quoted from JavaDoc, it should call hashCode() first and then call equals(), but the output is</p>
  
  <pre><code>invoking hashCode()1 //call put()
  invoking hashCode()2 //call put()
  invoking hashCode()2 //call containsKey()
  found
  </code></pre>
  
  <p>I am expecting there's another output line should be <code>invoking equals()</code>, can anyone explain this for me why equals() is not called?</p>