我一直在看着Collections.sort和list.sort之间的区别,特别是关于使用Comparator静态方法以及是否在lambda表达式中需要param类型。在我们开始之前,我知道我可以使用方法引用,例如。 Song :: getTitle来克服我的问题,但是我的查询不是我想要解决的东西,而是我想要的答案,即为什么是Java编译器以这种方式处理它。
这是我的发现。假设我们有一个类型为Song的ArrayList,添加了一些歌曲,有3个标准的get方法:
ArrayList playlist1 = new ArrayList();
//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()));
一旦我开始链接然后比较,以下发生:
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())
);
现在这里有CONFUSING部分。对于playlist1.sort,即List,这解决了所有编译错误,对于以下然后比较调用。然而,对于Collections.sort,它解决它的第一个,但不是最后一个。我测试添加几个额外的调用,然后比较,它总是显示一个错误的最后一个,除非我把(歌曲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 set = new TreeSet(
Comparator.comparing((Song p1) -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
同样的事情发生了,对于TreeSet,没有编译错误,但对于Objects.compare最后一次调用thenComparing显示一个错误。
任何人都可以解释为什么会发生这种情况,以及为什么不需要使用(歌曲p1)在所有当简单地调用比较方法(无进一步然后比较调用)。
对同一主题的另一个查询是当我对TreeSet这样做:
Set set = new TreeSet(
Comparator.comparing(p1 -> p1.getTitle())
.thenComparing(p1 -> p1.getDuration())
.thenComparing(p1 -> p1.getArtist())
);
即从比较方法调用的第一个lambda参数中删除类型Song,它显示在比较调用下的语法错误和第一次调用thenComparing但不是最后调用thenComparing – 几乎与上面发生的情况相反!而对于所有其他3个示例,即通过Objects.compare,List.sort和Collections.sort,当我删除第一个歌曲参数类型,它显示所有调用的语法错误。
提前谢谢了。
编辑以包括我在Eclipse Kepler SR2中收到的错误的屏幕截图,我现在自从发现是Eclipse特定的,因为当编译使用JDK8 java编译器在命令行上编译确定。