Przyglądałem się różnicy między Collections.sorti list.sort, w szczególności w odniesieniu do używania Comparatormetod statycznych i tego, czy typy parametrów są wymagane w wyrażeniach lambda. Zanim zaczniemy, wiem, że mógłbym użyć referencji do metod, np. Song::getTitleAby przezwyciężyć swoje problemy, ale moje zapytanie tutaj nie jest czymś, co chcę naprawić, ale czymś, na co chcę odpowiedzi, tj. Dlaczego kompilator Java obsługuje to w ten sposób .
Oto moje odkrycie. Załóżmy, że mamy ArrayListtyp Song, z dodanymi utworami, istnieją 3 standardowe metody pobierania:
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") );
Oto wywołanie obu typów metod sortowania, które działają, nie ma problemu:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle()));
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle()));
Gdy tylko zacznę łączyć thenComparing, dzieje się co następuje:
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())
);
tj. błędy składniowe, ponieważ nie zna już typu p1. Aby to naprawić, dodaję typ Songdo pierwszego parametru (porównania):
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())
);
Teraz czas na część Mylące. Dla p laylist1.sort, czyli Listy, rozwiązuje to wszystkie błędy kompilacji dla obu poniższych thenComparingwywołań. Jednak Collections.sortrozwiązuje to dla pierwszego, ale nie ostatniego. Testowałem dodałem kilka dodatkowych wywołań do thenComparingi zawsze pokazuje błąd dla ostatniego, chyba że wstawię (Song p1)parametr.
Teraz poszedłem dalej przetestować to, tworząc TreeSeti używając 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())
);
To samo dzieje się w przypadku TreeSet, nie ma błędów kompilacji, ale Objects.compareostatnie wywołanie thenComparingpokazuje błąd.
Czy ktoś może wyjaśnić, dlaczego tak się dzieje, a także dlaczego w ogóle nie ma potrzeby używania, (Song p1)gdy po prostu wywołuje metodę porównywania (bez dalszych thenComparingwywołań).
Jeszcze jedno zapytanie na ten sam temat dotyczy tego TreeSet:
Set<Song> set = new TreeSet<Song>(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
tzn. usuń typ Songz pierwszego parametru lambda dla wywołania metody porównującej, pokaże błędy składniowe pod wywołaniem porównania i pierwsze wywołanie, thenComparingale nie ostatnie wywołanie thenComparing- prawie odwrotność tego, co działo się powyżej! Podczas gdy dla wszystkich pozostałych 3 przykładów, tj. Z Objects.compare, List.sorti Collections.sortkiedy usuwam ten pierwszy Songtyp parametru, pokazuje on błędy składniowe dla wszystkich wywołań.
Z góry bardzo dziękuję.
Edytowano tak, aby zawierał zrzut ekranu błędów, które otrzymałem w Eclipse Kepler SR2, które teraz znalazłem, są specyficzne dla Eclipse, ponieważ po skompilowaniu za pomocą kompilatora JDK8 java w wierszu poleceń kompiluje się OK.
