0

I have class Point with overridden methods equals() и hashCode():

public class Point {
    private double x;
    private double y;

    public Point() {
    }

    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        Point point = (Point) obj;
        if (this.x != point.getX()) {
            return false;
        }
        if (this.y != point.getY()) {
            return false;
        }
        return true;
    }

    @Override
    public int hashCode() {
        return (int) (31 * x + y);
    }
}

I create points:

        p1 = new Point(1.0, 1.0);
        p2 = new Point(1.0, 2.0);
        p3 = new Point(1.0, 4.0);
        p4 = new Point(5.0, 5.0);

This is arrays of Points - combinations:

        Point[] combinationPoints1 = {p1, p2, p3};
        Point[] combinationPoints2 = {p1, p2, p4};
        Point[] combinationPoints3 = {p1, p3, p4};
        Point[] combinationPoints4 = {p2, p3, p4};

Create List<Point[]>:

List<Point[]> expectedResult = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

List<Point[]> expectedResult2 = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

Compare 2 List<Point[]> and get message true:

List<Point[]> expectedResult = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

List<Point[]> expectedResult2 = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

expectedResult.equals(expectedResult2);    // TRUE

When I'm try change order to this:

List<Point[]> expectedResult = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

List<Point[]> expectedResult2 = Arrays.asList(combinationPoints2, combinationPoints1, combinationPoints3, combinationPoints4);

When comparing, I get false:

expectedResult.equals(expectedResult2);    // FALSE

Why?

UPDATE 29.08.2020
I have 2 List<Point[]>:

// FIRST
List<Point[]> expectedResult = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

and

List<Point[]> actualResult = calculatePoint.getCombinationsElementsOver(startingPoints, pointsOnLine);

with contents:

for(Point[] p1 : expectedResult) {
            System.out.println(Arrays.toString(p1));
        }
// FIRST

[Point (1.0; 1.0), Point (1.0; 2.0), Point (1.0; 4.0)]
[Point (1.0; 1.0), Point (1.0; 2.0), Point (5.0; 5.0)]
[Point (1.0; 1.0), Point (1.0; 4.0), Point (5.0; 5.0)]
[Point (1.0; 2.0), Point (1.0; 4.0), Point (5.0; 5.0)]
for(Point[] p1 : actualResult) {
            System.out.println(Arrays.toString(p1));
        }

// SECOND
[Point (1.0; 1.0), Point (1.0; 2.0), Point (1.0; 4.0)]
[Point (1.0; 1.0), Point (1.0; 2.0), Point (5.0; 5.0)]
[Point (1.0; 1.0), Point (1.0; 4.0), Point (5.0; 5.0)]
[Point (1.0; 2.0), Point (1.0; 4.0), Point (5.0; 5.0)]

Through method I check identity lists:

private <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
        return new HashSet<>(list1).equals(new HashSet<>(list2));
    }

Why I get false when:

boolean result = listEqualsIgnoreOrder(expectedResult, actualResult);
West Side
  • 166
  • 3
  • 10
  • 3
    Because of the contract of `List.equals`, as stated in its docs: they're not equal by that definition. – Dave Newton Aug 28 '20 at 18:21
  • 4
    [Java ArrayList - how can I tell if two lists are equal, order not mattering?](https://stackoverflow.com/q/13501142) – 001 Aug 28 '20 at 18:22
  • Because arrays aren't equal to each other. You'd have better luck with a `List>`. – Louis Wasserman Aug 28 '20 at 18:24
  • 1
    The real point here is that equals for arrays doesn't work as you assume it would. If you would be using list of list of point things would be different. And note: mixing concepts is never a good approach. Either use arrays or lists, but lists of arrays is just weird. – GhostCat Aug 28 '20 at 18:25
  • @LouisWasserman, I'll check it out now and get answer – West Side Aug 28 '20 at 18:27
  • 1
    You have no (good) reason to use `Point[]`. You're better off using `List`. So `List` would be `List>`. – MC Emperor Aug 28 '20 at 18:33
  • @LouisWasserman, arrays are equal (see the update in the topic) – West Side Aug 29 '20 at 13:01
  • @n199a, no, they aren't. They have equal contents, but that doesn't make the _arrays_ `.equals` to each other. https://stackoverflow.com/q/8777257/869736 – Louis Wasserman Aug 29 '20 at 17:47

1 Answers1

1

These two lists have the same elements but in a different order:

List<Point[]> expectedResult = Arrays.asList(combinationPoints1, combinationPoints2, combinationPoints3, combinationPoints4);

List<Point[]> expectedResult2 = Arrays.asList(combinationPoints2, combinationPoints1, combinationPoints3, combinationPoints4);

The List.equals method considers two lists to be equal if they contain the "same" elements in the same order. These two lists do have the same elements, but they are not in the same order. So the equals method must return false.

There's also a potential issue that stems from the fact that arrays don't implement equals method based on the contents: two different arrays instances with the same contents are not considered "equal" by the equals method. That doesn't come to into play here though: all of your arrays have different contents anyway.

Joni
  • 108,737
  • 14
  • 143
  • 193