Java 8引入了streams和Comparator接口static/default方法 span> 可以轻松地根据各个字段的值比较两个对象,而无需在要比较其对象的类上实现 compare(T,T) 方法。
我将使用一个简单的 Song
类来帮助演示这一点,它的 Song.java
代码清单如下所示。 Song.java
package dustin.examples.jdk8; /** * Simple class encapsulating details related to a song * and intended to be used for demonstration of JDK 8. */ public class Song { /** Song title. */ private final String title; /** Album on which song was originally included. */ private final String album; /** Song's artist. */ private final String artist; /** Year song was released. */ private final int year; /** * Constructor accepting this instance's title, artist, and release year. * * @param newTitle Title of song. * @param newAlbum Album on which song was originally included. * @param newArtist Artist behind this song. * @param newYear Year song was released. */ public Song(final String newTitle, final String newAlbum, final String newArtist, final int newYear) { title = newTitle; album = newAlbum; artist = newArtist; year = newYear; } public String getTitle() { return title; } public String getAlbum() { return album; } public String getArtist() { return artist; } public int getYear() { return year; } @Override public String toString() { return "'" + title + "' (" + year + ") from '" + album + "' by " + artist; } }
刚刚显示的 Song
类缺少 compare
方法,但我们仍然可以很容易地比较 JDK 8 中此类的实例。根据刚刚显示的 Song
的类定义,可以使用以下代码对歌曲实例的 List
进行排序,顺序为发行年份、艺术家,最后专辑。
按年份、艺术家和专辑(按此顺序)对歌曲列表进行排序
/** * Returns a sorted version of the provided List of Songs that is * sorted first by year of song's release, then sorted by artist, * and then sorted by album. * * @param songsToSort Songs to be sorted. * @return Songs sorted, in this order, by year, artist, and album. */ private static List<Song> sortedSongsByYearArtistAlbum( final List<Song> songsToSort) { return songsToSort.stream() .sorted( Comparator.comparingInt(Song::getYear) .thenComparing(Song::getArtist) .thenComparing(Song::getAlbum)) .collect(Collectors.toList()); }
如果我静态导入 Comparator
和 Collectors
,上面的代码清单会稍微不那么冗长,但是包含这些接口仍然相当简洁和类名在列表中,对于关于这个主题的介绍性博客文章可能更有用。
在上面的代码清单中,static default
方法 Comparator.comparingInt 和 Comparator.thenComparing 用于对 Song
与底层 $ 按年份关联,然后按艺术家,最后按专辑。该代码具有很高的可读性,并允许基于任意单个访问器方法比较对象(以及对这些实例进行排序),而无需显式指定 List(用于每个比较访问器结果的自然排序顺序) .请注意,如果需要显式 Comparator,可以通过接受 Comparator 的同名重载方法将其提供给这些 static default 方法。
下一个代码清单是整个演示类。它包括刚刚显示的方法,还显示了由歌曲的未排序 List
构造的人为示例。
FineGrainSortingDemo.java
package dustin.examples.jdk8; import static java.lang.System.out; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; /** * Demonstration of easy fine-grained sorting in JDK 8 via * stream support for sorting and Comparator's static and * default method implementations. */ public class FineGrainSortingDemo { /** * Construct List of {@code Song}s. * * @return Instances of {@code Song}. */ private static List<Song> generateSongs() { final ArrayList<Song> songs = new ArrayList<>(); songs.add( new Song( "Photograph", "Pyromania", "Def Leppard", 1983)); songs.add( new Song( "Hysteria", "Hysteria", "Def Leppard", 1987)); songs.add( new Song( "Shout", "Songs from the Big Chair", "Tears for Fears", 1984)); songs.add( new Song( "Everybody Wants to Rule the World", "Songs from the Big Chair", "Tears for Fears", 1985)); songs.add( new Song( "Head Over Heels", "Songs from the Big Chair", "Tears for Fears", 1985 )); songs.add( new Song( "Enter Sandman", "Metallica", "Metallica", 1991 ) ); songs.add( new Song( "Money for Nothing", "Brothers in Arms", "Dire Straits", 1985 ) ); songs.add( new Song( "Don't You (Forget About Me)", "A Brass Band in African Chimes", "Simple Minds", 1985 ) ); return songs; } /** * Returns a sorted version of the provided List of Songs that is * sorted first by year of song's release, then sorted by artist, * and then sorted by album. * * @param songsToSort Songs to be sorted. * @return Songs sorted, in this order, by year, artist, and album. */ private static List<Song> sortedSongsByYearArtistAlbum( final List<Song> songsToSort) { return songsToSort.stream() .sorted( Comparator.comparingInt(Song::getYear) .thenComparing(Song::getArtist) .thenComparing(Song::getAlbum)) .collect(Collectors.toList()); } /** * Demonstrate fine-grained sorting in JDK 8. * * @param arguments Command-line arguments; none expected. */ public static void main(final String[] arguments) { final List<Song> songs = generateSongs(); final List<Song> sortedSongs = sortedSongsByYearArtistAlbum(songs); out.println("Original Songs:"); songs.stream().forEach(song -> out.println("\t" + song)); out.println("Sorted Songs"); sortedSongs.forEach(song -> out.println("\t" + song)); } }
运行上述代码的输出如下所示,其中列出了使用排序代码后新排序的 Song
。值得注意的是,此 stream.sorted()
操作不会更改原始 List
(它作用于流而不是 List
)。
Original Songs: 'Photograph' (1983) from 'Pyromania' by Def Leppard 'Hysteria' (1987) from 'Hysteria' by Def Leppard 'Shout' (1984) from 'Songs from the Big Chair' by Tears for Fears 'Everybody Wants to Rule the World' (1985) from 'Songs from the Big Chair' by Tears for Fears 'Head Over Heels' (1985) from 'Songs from the Big Chair' by Tears for Fears 'Enter Sandman' (1991) from 'Metallica' by Metallica 'Money for Nothing' (1985) from 'Brothers in Arms' by Dire Straits 'Don't You (Forget About Me)' (1985) from 'A Brass Band in African Chimes' by Simple Minds Sorted Songs 'Photograph' (1983) from 'Pyromania' by Def Leppard 'Shout' (1984) from 'Songs from the Big Chair' by Tears for Fears 'Money for Nothing' (1985) from 'Brothers in Arms' by Dire Straits 'Don't You (Forget About Me)' (1985) from 'A Brass Band in African Chimes' by Simple Minds 'Everybody Wants to Rule the World' (1985) from 'Songs from the Big Chair' by Tears for Fears 'Head Over Heels' (1985) from 'Songs from the Big Chair' by Tears for Fears 'Hysteria' (1987) from 'Hysteria' by Def Leppard 'Enter Sandman' (1991) from 'Metallica' by Metallica
JDK 8 引入了流以及接口中的默认方法和静态方法(特别是在本例中的 Comparator
上),这使得在没有任何显式 Comparator
的情况下以理想的顺序逐个字段地比较两个对象变得容易 而不是 static default
接口上的预构建 Comparator
方法,如果要比较的字段具有所需的自然顺序。
标签2: Java教程地址:https://www.cundage.com/article/jcg-easy-fine-grained-sorting-jdk-8.html