title: Why it is implied that objects are equal if compareTo() returns 0?
body: <p>Let's have a class <code>Person</code>.  Person has a name and height.</p>
  <p>Equals and hashCode() takes into account only name.  Person is comparable (or we implement comparator for it, does not matter which one).  Persons are compared by height.</p>
  <p>It seems reasonable to expect a situation where two different persons can have same height, but e.g. TreeSet behaves like compareTo()==0 means equals, not merely same size.</p>
  <p>To avoid this, comparison can secondarily look at something else if size is the same, but then it cannot be used to detect same sized different objects.</p>
  <p>Example:</p>
  <pre><code>import java.util.Comparator;
  import java.util.HashSet;
  import java.util.Objects;
  import java.util.Set;
  import java.util.TreeSet;
  
  public class Person implements Comparable&lt;Person&gt; {
  
  private final String name;
  private int height;
  
  public Person(String name,
          int height) {
      this.name = name;
      this.height = height;
  }
  
  public int getHeight() {
      return height;
  }
  
  public void setHeight(int height) {
      this.height = height;
  }
  
  public String getName() {
      return name;
  }
  
  @Override
  public int compareTo(Person o) {
      return Integer.compare(height, o.height);
  }
  
  public boolean equals(Object obj) {
      if (obj == null) {
          return false;
      }
      if (getClass() != obj.getClass()) {
          return false;
      }
      final Person other = (Person) obj;
      if (!Objects.equals(this.name, other.name)) {
          return false;
      }
      return true;
  }
  
  public int hashCode() {
      int hash = 5;
      hash = 13 * hash + Objects.hashCode(this.name);
      return hash;
  }
  
  public String toString() {
      return &quot;Person{&quot; + name + &quot;, height = &quot; + height + '}';
  }
  
  public static class PComparator1 implements Comparator&lt;Person&gt; {
  
      @Override
      public int compare(Person o1,
              Person o2) {
          return o1.compareTo(o2);
      }
  }
  
  public static class PComparator2 implements Comparator&lt;Person&gt; {
  
      @Override
      public int compare(Person o1,
              Person o2) {
          int r = Integer.compare(o1.height, o2.height);
          return r == 0 ? o1.name.compareTo(o2.name) : r;
      }
  }
  
  public static void test(Set&lt;Person&gt; ps) {
      ps.add(new Person(&quot;Ann&quot;, 150));
      ps.add(new Person(&quot;Jane&quot;, 150));
      ps.add(new Person(&quot;John&quot;, 180));
      System.out.println(ps.getClass().getName());
      for (Person p : ps) {
          System.out.println(&quot; &quot; + p);
      }
  }
  
  public static void main(String[] args) {
      test(new HashSet&lt;Person&gt;());
      test(new TreeSet&lt;Person&gt;());
      test(new TreeSet&lt;&gt;(new PComparator1()));
      test(new TreeSet&lt;&gt;(new PComparator2()));
  }
  }
  </code></pre>
  <p>result:</p>
  <pre><code>java.util.HashSet
   Person{Ann, height = 150}
   Person{John, height = 180}
   Person{Jane, height = 150}
  
  java.util.TreeSet
   Person{Ann, height = 150}
   Person{John, height = 180}
  
  java.util.TreeSet
   Person{Ann, height = 150}
   Person{John, height = 180}
  
  java.util.TreeSet
   Person{Ann, height = 150}
   Person{Jane, height = 150}
   Person{John, height = 180}
  </code></pre>
  <p>Do you have idea why it is so?</p>