Очень запутанный вывод типа компаратора Java 8
Я смотрел на разницу междуCollections.sort
а такжеlist.sort
в частности, относительно использованияComparator
статические методы и необходимость использования типов параметров в лямбда-выражениях. Прежде чем мы начнем, я знаю, что могу использовать ссылки на методы, например,Song::getTitle
чтобы преодолеть мои проблемы, но мой запрос здесь не столько что-то, что я хочу исправить, а что-то, на что я хочу получить ответ, т.е. почему компилятор Java обрабатывает его таким образом.
Это моя находка. Предположим, у нас естьArrayList
типаSong
с добавлением некоторых песен есть 3 стандартных метода get:
ArrayList<Song> playlist1 = new ArrayList<Song>();
//add some new Song objects
playlist.addSong( new Song("Only Girl (In The World)", 235, "Rhianna") );
playlist.addSong( new Song("Thinking of Me", 206, "Olly Murs") );
playlist.addSong( new Song("Raise Your Glass", 202,"P!nk") );
Вот вызов обоих типов метода сортировки, который работает, без проблем:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle()));
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle()));
Как только я начну цепочкуthenComparing
происходит следующее:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
то есть синтаксические ошибки, потому что он не знает типp1
больше. Таким образом, чтобы исправить это, я добавляю типSong
к первому параметру (сравнения):
Collections.sort(playlist1,
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
playlist1.sort(
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
Теперь здесь прибывает КОНФУЗИОННАЯ часть. Для рlaylist1.sort
то есть список, это решает все ошибки компиляции, для обоих следующихthenComparing
звонки. Однако дляCollections.sort
, это решает это для первого, но не последнего. Я проверил добавил несколько дополнительных звонковthenComparing
и он всегда показывает ошибку для последнего, если я не ставлю(Song p1)
для параметра.
Теперь я продолжил тестировать это дальше с созданиемTreeSet
и с использованиемObjects.compare
:
int x = Objects.compare(t1, t2,
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
Set<Song> set = new TreeSet<Song>(
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
То же самое происходит, что и дляTreeSet
нет ошибок компиляции, кроме какObjects.compare
последний звонокthenComparing
показывает ошибку.
Может кто-нибудь объяснить, почему это происходит, а также почему нет необходимости использовать(Song p1)
вообще при простом вызове метода сравнения (без дальнейшегоthenComparing
звонки).
Еще один запрос на ту же тему, когда я делаю это сTreeSet
:
Set<Song> set = new TreeSet<Song>(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
т.е. удалить типSong
из первого лямбда-параметра для вызова метода сравнения он показывает синтаксические ошибки при вызове сравнения и первом вызовеthenComparing
но не до последнего звонкаthenComparing
- почти противоположное тому, что происходило выше! Принимая во внимание, что для всех остальных 3 примеров, то есть сObjects.compare
, List.sort
а такжеCollections.sort
когда я уберу это первымSong
Тип param показывает синтаксические ошибки для всех вызовов.
Спасибо заранее.
Отредактировано, чтобы включить снимок экрана с ошибками, которые я получал в Eclipse Kepler SR2, которые, как я теперь обнаружил, специфичны для Eclipse, поскольку при компиляции с использованием java-компилятора JDK8 в командной строке он компилируется нормально.