Я готовлюсь к получению сертификата Java 8, и следующее меня немного озадачило, может, кто-нибудь может мне с этим помочь? В этом примере моделируется класс Squirrel. У него есть название и вес. Теперь вы можете создать класс Comparator для сортировки этой вещи, используя оба поля. Так что сначала сортируйте по имени, а затем по весу. Что-то вроде этого:
public class ChainingComparator implements Comparator<Squirrel> {
public int compare(Squirrel s1, Squirrel s2) {
Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies());
c = c.thenComparingInt(s -> s.getWeight());
return c.compare(s1, s2);
}
}
Пока все хорошо ... но затем загадочная часть. Под примером кода они заявляют, что вы можете написать это в одной строке, используя цепочку методов. Возможно, я неправильно понимаю, но когда я связываю части сравнение и thenComparing, я получаю ошибку компиляции. Это связано с типами сравниваемых объектов (сначала String, затем int).
Почему это работает, когда я добавляю промежуточную переменную, а не при связывании? И возможно ли вообще цепочка?




Да, это возможно - связывайте comparing(...) с thenComparing(...) и с compare(...), используя ссылки на методы вместо лямбда-выражений:
public int compare(Squirrel s1, Squirrel s2) {
return Comparator.comparing(Squirrel::getSpecies)
.thenComparing(Squirrel::getWeight)
.compare(s1, s2);
}
Почему так работает? Я не могу объяснить это лучше, чем Брайан в его отвечать подобному вопрос.
Кроме того, это можно переписать одной строкой (при условии, что у вас есть список белок, который вы хотите отсортировать):
list.sort(Comparator.comparing(Squirrel::getSpecies).thenComparing(Squirrel::getWeight));
При объединении обоих в цепочку компилятор не может вывести аргумент типа возвращаемого компаратора comparing(), поскольку он зависит от возвращенного компаратора thenComparingInt(), который сам по себе не может быть выведен.
Укажите тип в лямбда-параметре comparing() (или используйте ссылку на метод), и это решит проблему вывода, поскольку возвращаемый тип comparing() может быть выведен таким образом. :
Comparator<Squirrel> c = Comparator.comparing((Squirrel s) -> s.getSpecies())
.thenComparingInt(s -> s.getWeight());
Обратите внимание, что указав тип в лямбда-параметре thenComparingInt() (или используя ссылку на метод), например:
Comparator<Squirrel> c = Comparator.comparing(s -> s.getSpecies())
.thenComparingInt((Squirrel s) -> s.getWeight());
не будет работать как получатель (здесь тип возвращаемого значения связанного метода) не учитывается при вычислении типа вывода.
Это руководство / документация по JDK 8 очень хорошо это объясняет:
Note: It is important to note that the inference algorithm uses only invocation arguments, target types, and possibly an obvious expected return type to infer types. The inference algorithm does not use results from later in the program.
попробуйте этот `Comparator <Squirrel> c = Comparator.comparing ((Squirrel s) -> s.getSpecies ()). thenComparingInt (s -> s.getWeight ());`