-1

I am trying to compare if two lists have the same objects, independent of its order and its number of elements.

For example:

List1 ["A", "B", "A"] and List2 ["A", "B"] must return equals.

I am using Set, because checks independently of the order of objects. However, returns false if both lists have a different number of elements.

Here is my code:

private Optional<EArea> getSimilarExistingArea(EImportArea importedArea) {
    for (EArea existingArea : baseLineService.getBaseLine().getAreas()) {
        EList<EPoint> importedAreaPoints = importedArea.getPoly().getPoints();
        EList<EPoint> existingAreaPoints = existingArea.getPoly().getPoints();
        final Set<EPoint> importedAreaPointsSET = new HashSet<>(importedAreaPoints);
        final Set<EPoint> existingAreaPointsSET = new HashSet<>(existingAreaPoints);
        if (existingAreaPointsSET.equals(importedAreaPointsSET)) return Optional.of(existingArea);
    }
    return Optional.empty();
}

I would like to return true if existingAreaPointsSET ["A", "B", "A"] and importedAreaPointsSET["A", "B"]

Here are the equals and hashCode funtions in the EPoint class:

@Override
public boolean equals(Object o) {
    if (o == this)
        return true;
    if (!(o instanceof EPoint)) {
        return false;
    }
    EPoint ePoint = (EPoint) o;
    return Math.abs(Math.abs(ePoint.lat) - Math.abs(lat)) < EPSILON && Math.abs(Math.abs(ePoint.lon) - Math.abs(lon)) < EPSILON;
}

@Override
public int hashCode() {
    return Objects.hash(lat, lon);
}
Alex Blasco
  • 793
  • 11
  • 22
  • 1
    so, you have two lists with different contents, and you're suprirsed equals returns false? – Stultuske Oct 30 '17 at 11:02
  • 6
    Have you implemented `hashCode()` and `equals()` properly in `EPoint`? (Spoiler alert: you haven't). – Kayaman Oct 30 '17 at 11:02
  • 1
    In your examples, those sets can't contain a different number of elements since sets don't allow duplicates. If you add A, B, A to one, it will actually only hold A, B; same as the other set. – Carcigenicate Oct 30 '17 at 11:02
  • @Stultuske They aren't comparing lists of different sizes. – Carcigenicate Oct 30 '17 at 11:04
  • Yes I did @Kayaman – Alex Blasco Oct 30 '17 at 11:07
  • 2
    Can we see `EPoint` `equals` and `hashCode` method then ? – AxelH Oct 30 '17 at 11:07
  • @AxelH I know. I'm pointing out that "However, returns false if both lists have a different number of elements." probably isn't actually the problem. – Carcigenicate Oct 30 '17 at 11:09
  • @AxelH I edited in the main question – Alex Blasco Oct 30 '17 at 11:16
  • 2
    It is bothering me, you accept a marge of error in your equals method, but not in hashCode. So you have two "equals" `EPoint` with different `hashCode`, with `HashSet`, this is a problem since those instances will be in different buckets, they will not be compared together... check the rules about `hashCode`. And then you will notice that @Kayaman give you the answer 20min ago... – AxelH Oct 30 '17 at 11:19

2 Answers2

4

Your equals and hashCode definitions for EPoint are incorrect. Your equals method is actually an "approximately equals" method, while your hashCode method uses the exact values. Thus it is possible for two EPoint instances to compare equal but have different hashCodes. This breaks the precondition of HashSet and you therefore can't rely on it behaving the way you want after that.

DodgyCodeException
  • 5,963
  • 3
  • 21
  • 42
-1

Why not

list1.containsAll(list2) && list2.containsAll(list1);

?

EDIT: And why not commenting on why you're downvoting this?

daniu
  • 14,137
  • 4
  • 32
  • 53
  • 1
    Since you didn't comment much on your solution, I didn't though useful to comment either... (this is the reason by the way). I could argue the fact that this would not be efficient but this is not really the point. EDIT : the worst is that your solution would work since it doesn't need hashCode (even if this should still not be correctly implemented...). But this would need to be explained... – AxelH Oct 30 '17 at 11:41