How to translate following comparator into Comparator.comparing?

Viewed 174

My question may be unclear so let me clear it out by example:

Arrays.sort(arr, new Comparator<String>(){
    public int compare(String a, String b){
        return (b + a).compareTo(a + b);
    }
});

I want to use the Comparator.comparing. I tried out the following:

Arrays.sort(arr, Comparator.comparing((a, b) -> (b + a).compareTo((String)a + b)));

I get an error - bad return type in lamdba expression. How to fix this ?

3 Answers

Comparator.comparing method expects a keyExtractor of type Function. You just need a lambda to implement the Comparator<String> interface here:

Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));

It is impossible to turn that into a call to comparing because it's not a valid Comparator: it doesn't satisfy the Comparator contract, and you should never use it as a Comparator.

To prove it, that Comparator will compare every string as equal to "", but not every string will be equal to each other. That violates the transitivity property.

As already answered, your anonymous class implementation can be shortened into a lambda expression:

Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));

If you insist on using Comparator.comparing(), remember it has specific parameters that don't fit your sorting problem.

  • The Comparator.comparing(keyExtractor) returns a specified Comparator for certain key based on the natural way of comparison (Comparator.naturalOrder). Your method doesn't say what is compared, but how it is.
  • The Comparator.comparing(keyExtractor, keyComparator) looks a bit better because you can specify how the specified keys are compared using keyComparator. You can use your logics of comparing and you conclude to:

    Arrays.sort(arr, Comparator.comparing(
        Function.identity(),                  // keyExtractor, WHAT is compared
        (a, b) -> (b + a).compareTo(a + b))); // keyComparator, HOW is it compared
    

    This is a solution using Comparator.comparing that uses a keyExtractor the Function.identity() returning the input back (the same like str -> str lambda expression) since you want still compare the Strings but in a different way specified with a custom Comparator, therefore the only correct way to sort the array as you need is the simplified version omitting the keyExtractor:

    Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));
    

    ... which is finally where we started at.

Related