Как перевести следующий компаратор в Comparator.comparing? - PullRequest
2 голосов
/ 05 апреля 2020

Мой вопрос может быть неясным, поэтому позвольте мне прояснить его на примере:

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

Я хочу использовать Comparator.comparing. Я попробовал следующее:

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

Я получаю ошибку - неверный тип возврата в выражении lamdba. Как это исправить?

Ответы [ 3 ]

6 голосов
/ 05 апреля 2020

Comparator.comparing метод ожидает keyExtractor типа Function. Вам просто нужна лямбда для реализации интерфейса Comparator<String> здесь:

Arrays.sort(arr, (a, b) -> (b + a).compareTo(a + b));
3 голосов
/ 05 апреля 2020

Невозможно превратить это в вызов сравнения, потому что он не является действительным компаратором: он не удовлетворяет контракту компаратора, и вы никогда не должны использовать его в качестве компаратора.

Чтобы доказать это, этот компаратор будет сравнивать каждую строку как равную "", но не каждая строка будет равна друг другу. Это нарушает свойство транзитивности.

1 голос
/ 06 апреля 2020

Как уже отвечено, ваша анонимная реализация класса может быть сокращена до лямбда-выражения:

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

Если вы настаиваете на использовании Comparator.comparing(), помните, что оно имеет спецификацию c параметры, которые не соответствуют вашей проблеме сортировки.

  • Comparator.comparing(keyExtractor) возвращает указанный Comparator для определенного ключа на основе естественного способа сравнения (Comparator.naturalOrder). Ваш метод не говорит , что сравнивается, но как .
  • Comparator.comparing(keyExtractor, keyComparator) выглядит немного лучше потому что вы можете указать , как сравнивать указанные ключи, используя keyComparator. Вы можете использовать свою логику сравнения и сделать вывод:

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

    Это решение, использующее Comparator.comparing, использующее keyExtractor * Function.identity(), возвращающее ввод обратно (аналогично str -> str лямбда-выражение), поскольку вы все равно хотите сравнить строки, но другим способом, указанным с помощью пользовательского Comparator, поэтому единственный правильный способ сортировки массива по мере необходимости - это упрощенная версия, в которой пропущено keyExtractor:

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

    ... что, наконец, мы и начали.

...