-1

I've attempted to sort a Java ArrayList by using Collections, but it's not working, even though I tried to follow code from other questions.

I have a class called PcdPoint that has the methods getScore() and getType(), where getScore() returns a double and getType() returns an integer. (not Atomic)

The following code should work but it's giving me an error: "Cannot infer type <any>"

Collections.sort(pointList,
            Comparator.comparing((PcdPoint a, PcdPoint b) -> a.getScore() - b.getScore())
            .thenComparing((PcdPoint a, PcdPoint b) -> a.getType() - b.getType()));

So I tried looking up the documentation and tried to do this instead

Collections.sort(pointList,
            Comparator<PcdPoint>.comparing((a, b) -> a.getScore() - b.getScore())
            .thenComparing((a, b) -> a.getType() - b.getType()));

and

Collections.sort(pointList,
            Comparator.comparing((a, b) -> a.getScore() - b.getScore())
            .thenComparing((a, b) -> a.getType() - b.getType()));

But neither of those seem to work.

Jack Avante
  • 1,405
  • 1
  • 15
  • 32
  • 3
    First, subtracting a `double` from a `double` results in a `double` but a comparator’s `compare` method has to return `int`. Besides that, using minus as a comparator implementation is broken in general, because it can overflow. And you’re mixing up two ways of implementing a comparator. Either, implement a complete comparator, e.g. `(PcdPoint a, PcdPoint b) -> Double.compare(a.getScore(), b.getScore()` or use one of the factory methods providing a getter method: `Comparator.comparing((PcdPoint p) -> p.getScore())` or even better `Comparator.comparingDouble(PcdPoint::getScore)`. – Holger Mar 19 '21 at 09:08

1 Answers1

1

If you want to sort by score first, and then by type your comparator should look like this.

Collections.sort(pointList, 
    Comparator.comparingDouble(PcdPoint::getScore)
        .thenComparingInt(PcdPoint::getType));
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
  • That does compile and run correctly but it has unexpected behavior. It is sorted correctly by score first, but then it isn't correctly sorted by type (a:0, c:0, b:0, c:1, b:1, a:1). When I change the order, it correctly sorts by type first (a, b, c) and then sorts each type list by score (a:0, a:1, b:0, b:1, c:0, c:1) – Jack Avante Mar 19 '21 at 09:17
  • @Holger thanks for bringing that in ! I have made a mistake there. – Ravindra Ranwala Mar 19 '21 at 09:19
  • 2
    @JackAvante it doesn’t sort multiple times. You are creating a comparator with a first (primary) order and a secondary order. The list is sorted once according to the specified comparator. That is exactly the expected behavior. If “type” is your primary sorting criteria, specify it first, i.e. `Comparator.comparingInt(PcdPoint::getType) .thenComparingDouble(PcdPoint::getScore)`. Mind the words “comparing” and “then comparing”, not “sorting” and “sorting again”. – Holger Mar 19 '21 at 09:23