-2

I have this class

public class Point {
    private Double[] coordinates;
    private int dimension;

    public Point(Double[] coordinates) {
        dimension = coordinates.length;
        this.coordinates = new Double[dimension];

        for(int i = 0; i < dimension; i++)
            this.coordinates[i] = coordinates[i];


    }

    public Double getCoord(int n) {
        if(n < 0 || n > dimension -1 ){
            throw new RuntimeException("error de coordenadas");
        }
        return coordinates[n];
    }
    public int getDim() {
        return dimension;
    }

    public boolean equals(Object p1){
        if( (p1 instanceof Point) ){
            Point p = (Point) p1;
            int n = p.getDim();
            if(getDim() == n)
            {
                for(; n > 0; n--)
                {
                    if( Double.valueOf(this.getCoord(n-1)) != Double.valueOf(p.getCoord(n-1)) ) // <------- BAD LINE!
                    {
                        System.out.println("Checking coord " + (n-1));
                        System.out.println("Coord " + (n-1) + " p = " + Double.valueOf(this.getCoord(n-1)));
                        System.out.println("Coord " + (n-1) + " p2 = " + Double.valueOf(p.getCoord(n-1)));
                        return false;
                    }
                }
            }
            return true;
        }
        return false;
    }
}

And this main

public class FigureTest {
    public static void main(String[] args){
        Double[] coord1 = {2.0,3.3};
        Double[] coord2 = {2.0,3.3};
        Point p = new Point(coord1);
        Point q = new Point(coord2);
        System.out.println(p.equals(q));
    }
}

I can't understand why this p.equals(q) returns false! It goes inside the if( Double.valueOf(... but then prints that both coordinates are equal. It's the same if I remove the Double.valueOf. The only way it worked was when I put ! if(this.getCoord(n-1).equal(p.getCoord(n-1)), but I don't understand why the others don't work.

Pshemo
  • 113,402
  • 22
  • 170
  • 242
YoTengoUnLCD
  • 619
  • 7
  • 14
  • 1
    Do you understand the difference between `p.equals(q)` and `p == q`? (What does `==` do when used with objects?) – Radiodef Apr 13 '16 at 17:33
  • why don't you use just `Arrays.equals()` in `Point#equals()` method? – Alex Salauyou Apr 13 '16 at 17:34
  • @Radiodef if `.equals` was not overwritten, then it would be the same as `==` : comparing references, right? Else, the equals method of `p`'s class would be called. – YoTengoUnLCD Apr 13 '16 at 17:36
  • @YoTengoUnLCD Yes, exactly, and it works the same way with `Double`. `==` compares references where `equals` compares value. – Radiodef Apr 13 '16 at 17:37
  • @SashaSalauyou Because I didn't know that method, I'm just a begginer. However, I want to know mostly why what I did doesn't work, rather than how to actually implement this. – YoTengoUnLCD Apr 13 '16 at 17:37
  • 1
    because you confuse `Double.valueOf()` with `Double#doubleValue()` – Alex Salauyou Apr 13 '16 at 17:41
  • @SashaSalauyou Sorry, I haven't yet learned what the `#` is... However I did understand Radiodef's and Vince Emighs' explanation. – YoTengoUnLCD Apr 13 '16 at 17:42
  • @Radiodef, Vince Emigh thank you!! I finally understand what I was doing wrong. – YoTengoUnLCD Apr 13 '16 at 17:43
  • `#` means "instance method", i. e. `this.getCoord(n - 1).doubleValue()`: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#doubleValue%28%29 – Alex Salauyou Apr 13 '16 at 17:43

2 Answers2

4

Double.valueOf returns a Double object, not a primitive double.

You perform a reference check (!=). So even if Double.valueOf(getCoords(n-1)) returned the same numeric value for both calls, different objects would be wrapping the numbers, so the != check would be true, causing your equals to return false.

Here's a quick example:

public static void main(String[] args){
    System.out.println(Double.valueOf(5) == Double.valueOf(5));
}

Notice how it returns false. That's because == is a reference check, and a different object is being returned each time you call Double.valueOf. So when you do

Double.valueOf(...) != Double.valueOf(...)

That check will return true, since the valueOf calls didn't return the same object. This is why the check in your code returns true, resulting in equals returning false.


To fix this, you could...

Change your != check into a .equals check, which will compare the numeric values rather than the references.

Double.valueOf(...).equals(Double.valueOf(...));

This returns true if both share the same numeric value.

Or you could use doubleValue() when you call getCoord:

getCoord(n-1).doubleValue() != other.getCoord(n-1).doubleValue()

This will avoid the excess creation of Double objects.

Dioxin
  • 13,042
  • 5
  • 35
  • 70
-3

In order to this to work;:

p.equals(q)

you need to keep the contract between Hashcode and equals and override properly both of them: equals AND hashcode in the class Point, and when I write properly I mean specifically this:

Please refer to this question if you dont know why or that you dont need it

Double.valueOf(this.getCoord(n-1)) != Double.valueOf(p.getCoord(n-1))

if the members of the class Point are doubles, then you are right when you compare those doubles as criteria to decide if p1.equals(p2)

but according to the documentation of the class Double, the static method Double.compare(this.getCoord(n-1)),p.getCoord(n-1) must be use in order to compare 2 doubles content.

hence I recommend to do in the equals method some similar to this

if( Double.compare(this.getCoord(n-1)),p.getCoord(n-1)!=0) ) 
Community
  • 1
  • 1
ΦXocę 웃 Пepeúpa ツ
  • 43,054
  • 16
  • 58
  • 83
  • 1
    why should they implement `hashCode()`??? No hash collections are used here. And they *have implemented* equals(), and the question is "why don't it work". – Alex Salauyou Apr 13 '16 at 17:39
  • 1
    @SashaSalauyou - It is just good practice to override hashCode() when you override equals() though it is not required in this case. But in general a class writer must ensure that both the methods are provided if one of them is. – MS Srikkanth Apr 13 '16 at 17:42
  • 2
    @user3493289 agree, it is a good practice. But not related to the question in any way. Answer states "you need", as if implementing it would solve the problem. – Alex Salauyou Apr 13 '16 at 17:46