0

I created an IntPair class as following

  class IntPair {
  public int x;
  public int y;
    
    public IntPair(int x, int y) {
        this.x = x;
        this.y = y;
    }
    
    @Override
    public boolean equals(Object o) {
        
        if(this == o)
            return true;
        
        if(!(o instanceof IntPair))
            return false;
        
        IntPair p = (IntPair) o;
        
        return x == p.x && y == p.y; 
    }
    
    @Override
    public String toString() {
        return "(" + x + ", " + y + ")";
    }
}

When I try something like the following

System.out.println(Arrays.asList(new IntPair(1,2), new IntPair(1,2)).stream()
                                    .distinct()
                                    .collect(Collectors.toList())
        );

I get as result a list of two IntPairs, that is

[(1, 2), (1, 2)]

even if those two pairs are equal. Why?

Matteo
  • 539
  • 3
  • 9
  • 7
    When overriding `equals` you should also override `hashcode`. If two objects are equal then their hashcode should also be equal. – Pshemo Apr 24 '21 at 09:00
  • 1
    Thank you, I forgot about that. It now works. – Matteo Apr 24 '21 at 09:10
  • 1
    Indeed, I too get `[(1, 2), (1, 2)]`. It’s a bug. [The documentation of `Stream.distinct()`](https://docs.oracle.com/javase/10/docs/api/java/util/stream/Stream.html#distinct()) claims that it is based on `Objects.equals()` alone and makes no mention of hash code. – Ole V.V. Apr 24 '21 at 09:21
  • @OleV.V. That behavior and expectation for `Object.hashCode` is coupled with the `Object.equals` documentation if you follow the links. – Naman Apr 24 '21 at 09:31
  • @Naman *Note that it is generally necessary to override the hashCode method whenever this method [`equals()`] is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.* Well, I find that a very indirect way of saying what you say. At best. – Ole V.V. Apr 24 '21 at 09:38
  • 2
    @OleV.V. The OP is overriding the method `equals` and the contract of `equals` has that statement. There’s nothing “indirect” here. Programmers should never override a method without consulting its contract. There shouldn’t be a need to repeat the contract at every place where the method is mentioned. – Holger Apr 26 '21 at 11:04

0 Answers0