10

I need to sort a list of Points. First I need to compare the x value, then if the x values are equal, the y value. So I thought I'd use the thenComparing method:

Comparator<Point> cmp = Comparator.comparingInt(p -> p.x).thenComparingInt(p -> p.y);

But I keep getting the message: Incompatible types: Comparator<Object> cannot be converted to Comparator<Point>.

There are other ways I can make this comparison, and it works, but I don't understand what I'm doing wrong here.

fwend
  • 1,813
  • 2
  • 15
  • 17

2 Answers2

18

This code does work:

Comparator<Point> cmp = Comparator.<Point> comparingInt(p -> p.x)
                                  .thenComparingInt(p -> p.y);

I only added <Point> before comparingInt, which explicitly declares the type of p in the lambda. This is necessary, since Java cannot infer the type, due to the method chain.

See also Generic type inference not working with method chaining?


Here is another alternative:

Comparator<Point> cmp = Comparator.comparingDouble(Point::getX)
                                  .thenComparingDouble(Point::getY);

Here, the type can be inferred without any problems. However, you need to use the double comparison, because getX and getY return double values. I personally prefer this approach.

Community
  • 1
  • 1
Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51
  • Why not something like ```Collections.sort(list, (p1, p2) -> p1.x != p2.x ? p1.x - p2.x : (double) (p1.y - p2.y)``` ? – bit_cracker007 Oct 14 '21 at 23:52
  • You are suggesting to use the following comparator: `Comparator cmp = (p1, p2) -> p1.x != p2.x ? p1.x - p2.x : p1.y - p2.y;` I just took some time to verify that it is doing the right thing and that indeed seems to be the case. But this is just what, in my opinion, makes your suggestion bad coding style: It is not self-explaining and it potentially duplicates code, so you have to think about it every time you write down a comparator, which easily leads to bugs that are hard to find. – Stefan Dollase Oct 24 '21 at 13:58
4

Try changing:

Comparator<Point> cmp = Comparator.comparingInt(p -> p.x).thenComparingInt(p -> p.y);

to

Comparator<Point> cmp = Comparator.comparingInt((Point p) -> p.x).thenComparingInt((Point p) -> p.y);
Darshan Mehta
  • 30,102
  • 11
  • 68
  • 102