我有一个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))));
我想对它们进行排序,以使
Something
对象根据(Anything
对象)noThings
的总降序总和排序,然后再根据(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))));
我知道我可以获得每个父母
Anything
的Id
列表Map<Integer, List<Anythings>> anythings
= mySomethings.stream()
.collect(Collectors.toMap(p->p.getParentId(),
p->p.getAnythings()))
;
但是之后,我有点卡住了。
最佳答案
除非我弄错了,否则您一口气都无法做到这两种。但由于它们彼此独立(nothings
中Anythings
中Something
中Anytings
的总和与它们的顺序无关),所以这无关紧要。只是一个接一个地排序。
要将Somethings
内的noThings
按其Somethings
排序:
mySomethings.stream().map(Something::getAnythings)
.forEach(as -> as.sort(Comparator.comparing(Anything::getNoThings)
.reversed()));
按照
noThings
的Anythings
的总和对进行排序:mySomethings.sort(Comparator.comparing((Something s) -> s.getAnythings().stream()
.mapToInt(Anything::getNoThings).sum())
.reversed());
请注意,这两种排序都会就地修改相应的列表。
正如@Tagir指出的那样,第二种排序将再次为排序中比较的每一对Somethings计算Anything的总和。如果列表很长,这可能非常浪费。相反,您可以先在地图中计算总和,然后仅查找值。
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());