我有一个类Something
,其中包含一个实例变量Anything
。
class Anything {
private final int id;
private final int noThings;
public Anything(int id, int noThings) {
this.id = id;
this.noThings = noThings;
}
}
class Something {
private final int parentId;
private final List<Anything> anythings;
private int getParentId() {
return parentId;
}
private List<Anything> getAnythings() {
return anythings;
}
public Something(int parentId, List<Anything> anythings) {
this.parentId = parentId;
this.anythings = anythings;
}
}
给定一个Something
列表
List<Something> mySomethings = Arrays.asList(
new Something(123, Arrays.asList(new Anything(45, 65),
new Anything(568, 15),
new Anything(145, 27))),
new Something(547, Arrays.asList(new Anything(12, 123),
new Anything(678, 76),
new Anything(98, 81))),
new Something(685, Arrays.asList(new Anything(23, 57),
new Anything(324, 67),
new Anything(457, 87))));
我想对它们进行排序,以便根据(Anything
对象)noThings
的总降序总和对 Something
对象进行排序,然后按 (Anything
对象) noThings
的降序值
123 = 65+15+27 = 107(3rd)
547 = 123+76+81 = 280 (1st)
685 = 57+67+87 = 211 (2nd)
所以我最终得到
List<Something> orderedSomethings = Arrays.asList(
new Something(547, Arrays.asList(new Anything(12, 123),
new Anything(98, 81),
new Anything(678, 76))),
new Something(685, Arrays.asList(new Anything(457, 87),
new Anything(324, 67),
new Anything(23, 57))),
new Something(123, Arrays.asList(new Anything(45, 65),
new Anything(145, 27),
new Anything(568, 15))));
我知道我可以获得每个父Id
的Anything
列表
Map<Integer, List<Anythings>> anythings
= mySomethings.stream()
.collect(Collectors.toMap(p->p.getParentId(),
p->p.getAnythings()))
;
但在那之后我有点卡住了。
最佳答案
除非我弄错了,否则你不能一次性完成这两种操作。但由于它们彼此独立(Something
中的 Anythings
中的 nothings
之和与它们的顺序无关),因此没关系。只需一个接一个地排序即可。
要按 NoThings
对 Somethings
内的 Anytings
进行排序:
mySomethings.stream().map(Something::getAnythings)
.forEach(as -> as.sort(Comparator.comparing(Anything::getNoThings)
.reversed()));
要按 Anythings
的 noThings
总和对 Somethings
进行排序:
mySomethings.sort(Comparator.comparing((Something s) -> s.getAnythings().stream()
.mapToInt(Anything::getNoThings).sum())
.reversed());
请注意,这两种排序都会就地修改相应的列表。
正如 @Tagir 所指出的,第二个排序将再次计算排序中比较的每对 Somethings 的 Anythings 总和。如果列表很长,这可能会非常浪费。相反,您可以首先计算 map 中的总和,然后查找值。
Map<Something, Integer> sumsOfThings = mySomethings.stream()
.collect(Collectors.toMap(s -> s, s -> s.getAnythings().stream()
.mapToInt(Anything::getNoThings).sum()));
mySomethings.sort(Comparator.comparing(sumsOfThings::get).reversed());
关于java 8流分组按复合变量之和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30888545/