Tôi đã xem xét sự khác biệt giữa Collections.sort
và list.sort
, đặc biệt liên quan đến việc sử dụng các Comparator
phương thức tĩnh và liệu các kiểu tham số có được yêu cầu trong các biểu thức lambda hay không. Trước khi chúng ta bắt đầu, tôi biết tôi có thể sử dụng tham chiếu phương thức, ví dụ: Song::getTitle
để khắc phục sự cố của mình, nhưng truy vấn của tôi ở đây không phải là thứ tôi muốn sửa mà là thứ tôi muốn có câu trả lời, tức là tại sao trình biên dịch Java lại xử lý nó theo cách này .
Đây là phát hiện của tôi. Giả sử chúng ta có một ArrayList
loại Song
, với một số bài hát được thêm vào, có 3 phương thức lấy tiêu chuẩn:
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") );
Đây là lời gọi đến cả hai loại phương thức sắp xếp hoạt động, không vấn đề gì:
Collections.sort(playlist1,
Comparator.comparing(p1 -> p1.getTitle()));
playlist1.sort(
Comparator.comparing(p1 -> p1.getTitle()));
Ngay khi tôi bắt đầu xâu chuỗi thenComparing
, những điều sau sẽ xảy ra:
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())
);
tức là lỗi cú pháp vì nó không biết kiểu p1
nữa. Vì vậy, để khắc phục điều này, tôi thêm kiểu Song
vào tham số đầu tiên (so sánh):
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())
);
Bây giờ đến phần KẾT NỐI. Đối với p laylist1.sort
, tức là Danh sách, điều này giải quyết tất cả các lỗi biên dịch, cho cả hai lần thenComparing
gọi sau . Tuy nhiên, đối với Collections.sort
, nó giải quyết nó cho cái đầu tiên, nhưng không phải cái cuối cùng. Tôi đã thử nghiệm thêm một số cuộc gọi bổ sung vào thenComparing
và nó luôn hiển thị lỗi cho cuộc gọi cuối cùng, trừ khi tôi đặt (Song p1)
tham số.
Bây giờ tôi đã tiếp tục kiểm tra điều này hơn nữa với việc tạo TreeSet
và sử dụng 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())
);
Điều tương tự cũng xảy ra như trong, đối với TreeSet
, không có lỗi biên dịch nhưng đối Objects.compare
với cuộc gọi cuối cùng thenComparing
hiển thị lỗi.
Bất cứ ai có thể vui lòng giải thích tại sao điều này đang xảy ra và cũng là lý do tại sao không cần phải sử dụng (Song p1)
chút nào khi chỉ cần gọi phương thức so sánh (mà không cần thenComparing
gọi thêm ).
Một truy vấn khác về cùng chủ đề là khi tôi thực hiện điều này với TreeSet
:
Set<Song> set = new TreeSet<Song>(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
tức là loại bỏ kiểu Song
khỏi tham số lambda đầu tiên cho cuộc gọi phương thức so sánh, nó hiển thị lỗi cú pháp trong lệnh gọi so sánh và lệnh gọi đầu tiên thenComparing
nhưng không đến lệnh gọi cuối cùng thenComparing
- gần như ngược lại với những gì đang xảy ra ở trên! Trong khi đó, đối với tất cả 3 ví dụ khác tức là với Objects.compare
, List.sort
và Collections.sort
khi tôi loại bỏ đầu tiên Song
loại param nó show cú pháp lỗi cho tất cả các cuộc gọi.
Rất cám ơn trước.
Đã chỉnh sửa để bao gồm ảnh chụp màn hình các lỗi tôi đã nhận được trong Eclipse Kepler SR2, mà tôi đã tìm thấy kể từ đó là Eclipse cụ thể vì khi biên dịch bằng trình biên dịch java JDK8 trên dòng lệnh, nó biên dịch OK.