如何使用partitioningBy,然后使用Java Streams分别对结果列表进行排序



我有一个像这样的对象:

public class Resource {
int level;
String identifier;
boolean isEducational;
public Resource(String level, String identifier, boolean isEducational) {
this.level = level;
this.identifier = identifier;
this.isEducational = isEducational;
}
// getter and setters 
}

和这些资源的列表,如:

List<Resource> resources = Arrays.asList(new Resource(4, "a", true ),
new Resource(4, "b", false),
new Resource(3, "c", true ),
new Resource(3, "d", false ),
new Resource(2, "e", true ),
new Resource(2, "f" , false));

我想按照它们的level属性对列表进行排序,但是对于isEducational资源和,应该分别进行排序。—isEducational资源。

因此,排序后的结果列表应该按照以下顺序:

[Resource e, Resource c, Resource a, Resource f, Resource d, Resource b]
// basically, isEducational sorted first, followed by non-educational resources

所以我尝试如下:

List<Resource> resources1 = resources.stream()
.collect(partitioningBy(r -> r.isEducational()))
.values()
.stream()
.map(list -> {
return list
.stream()
.sorted(comparing(r -> r.getLevel()))
.collect(toList());
})
.flatMap(Collection::stream)
.collect(toList());

resources1.stream().forEach(System.out::println);

输出如下:

Resource{level='2', identifier='f', isEducational='false'}
Resource{level='3', identifier='d', isEducational='false'}
Resource{level='4', identifier='b', isEducational='false'}
Resource{level='2', identifier='e', isEducational='true'}
Resource{level='3', identifier='c', isEducational='true'}
Resource{level='4', identifier='a', isEducational='true'}

这与我想要的相反,即它首先打印非教育类,然后是教育资源

有更好的方法来实现这一点吗?我不想再次迭代列表来重新排列它。谢谢。

不需要使用partitioningBy。您只需要两个比较器,首先通过isEducational进行比较,然后通过level进行比较,您可以使用Comparator.thenComparing

将它们连接起来。
resources.stream()
.sorted(Comparator.comparing(Resource::isEducational).reversed().thenComparing(Resource::getLevel))
.forEach(System.out::println);

您可以为比较器引入变量,以使您的代码更具可读性,或者如果您想以灵活的方式重用它们:

Comparator<Resource> byIsEdu = Comparator.comparing(Resource::isEducational).reversed();
Comparator<Resource> byLevel = Comparator.comparing(Resource::getLevel);
resources.stream()
.sorted(byIsEdu.thenComparing(byLevel))
.forEach(System.out::println);