我一直在研究Collections.sort
和之间的区别list.sort
,特别是在使用Comparator
静态方法以及lambda表达式中是否需要参数类型方面。在开始之前,我知道我可以使用方法引用Song::getTitle
来解决问题,例如,这里的查询不是我想要修复的东西,而是我想要解决的东西,即Java编译器为什么以这种方式处理它。
这些是我的发现。假设我们有一个ArrayList
type 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())
);
现在到了混淆部分。对于p laylist1.sort
,即List,这可以解决以下两个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
从用于比较方法调用的第一个lambda参数中删除类型,它显示了在进行比较的调用和对的第一个调用(thenComparing
但对最终调用没有)下的语法错误thenComparing
-几乎与上述情况相反!然而,所有其他3个例子,即有Objects.compare
,List.sort
而且Collections.sort
当我删除第一个Song
参数类型它显示语法错误的所有电话。
提前谢谢了。
经过编辑,其中包括我在Eclipse Kepler SR2中收到的错误的屏幕截图,此后我现在发现它们是针对Eclipse的,因为在命令行上使用JDK8 java编译器进行编译时,它可以编译。