2

This is my code:

private class UniqueClassByTwoIntProperties {
    private final int propertyOne;
    private final int propertyTwo;

    UniqueCase(final int propertyOne, final int propertyTwo) {
        this.propertyOne= propertyOne;
        this.propertyTwo= propertyTwo;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (this == obj) {
            return true;
        }

        if (!(obj instanceof UniqueCase)) {
            return false;
        }

        UniqueClassByTwoIntProperties unique = (UniqueClassByTwoIntProperties) obj;

        return unique.claimApplicationId == claimApplicationId && unique.claimCoverageId == claimCoverageId;
    }

    @Override
    public int hashCode() {
        return Objects.hash(propertyOne, propertyTwo);
    }
}

I am looping through a list with objects, where I want to get the unique's in the following way:

myList.stream()
      .map(row -> new UniqueClassByTwoIntProperties(row.getOne(), row.getTwo()))
      .collect(Collectors.toSet());

I was wondering if there was a build-in class/method in Java. I have looked into dictionaries and MultiMapValues, but it was a bit hacky.

J. Doe
  • 12,159
  • 9
  • 60
  • 114
  • 4
    `return unique.hashCode() == hashCode();` WHAT? **NO!** This is of course horribly broken, `hashCode` has the variable space of `int` - two `int` have the variable space of `long`. That is literally the point of `hashCode` - two items that are _not `equals`_ **may** have the same `hashCode()` but two items that _are `equals`_ **must** have same `hashCode()`. Please, please **please** read [this SO answer](https://stackoverflow.com/a/2265637/2071828). Your code it fundatemally and catastrophically broken. – Boris the Spider Dec 05 '18 at 12:39
  • What is the type of `myList`? – DodgyCodeException Dec 05 '18 at 12:54
  • @BoristheSpider Woops, I am embarresed about that mistake. I hope I properly implemented it now – J. Doe Dec 05 '18 at 13:24

1 Answers1

4

You can simply do it as:

Set<UniqueClassByTwoIntProperties> uniques = new HashSet<>(myList);

Aside: Make sure the hashCode and equals of the objects are implemented correctly for the object to be comparable.

If you just want the List of uniques then you can use Stream.distinct as :

List<UniqueClassByTwoIntProperties> uniques = myList.stream()
                                 .distinct() // for unique objects
                                 .collect(Collectors.toList());
Naman
  • 27,789
  • 26
  • 218
  • 353
  • 1
    Apart from the broken `equals` which will cause `Set` to behave very strangely. – Boris the Spider Dec 05 '18 at 12:43
  • 1
    @BoristheSpider Agreed, that's what made me place that side note. Though answering to focus on the actual question. – Naman Dec 05 '18 at 12:44
  • As another aside, in the OPs example they are using a `Stream` - could you mention `Collectors.toSet()` and `distinct()`? (+1 either way) – Boris the Spider Dec 05 '18 at 12:45
  • @BoristheSpider `distinct` is not required while collecting `toSet`, hence the current solution proposed with the use of streams is correct. – Naman Dec 05 '18 at 12:46
  • I meant as two alternatives. If the OP wants a `List` of unique items then `distinct` will do the trick. Otherwise `toSet`. Your answer only covers copying the `List` to a `Set` after already building the `List`. The answer doesn't quite avoid the OPs problem as the OP needs to create the `UniqueClassByTwoIntProperties` - this seems to be a way to "override" equality for the sake of this particular uniqueness constraint. – Boris the Spider Dec 05 '18 at 12:46
  • @BoristheSpider Mentioned in the answer about the two alternatives. – Naman Dec 05 '18 at 12:53