java 8流分组按复合变量之和

标签 java sorting java-8 grouping java-stream

我有一个类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))));

我知道我可以获得每个父IdAnything列表

Map<Integer, List<Anythings>> anythings
            = mySomethings.stream()
            .collect(Collectors.toMap(p->p.getParentId(),
                    p->p.getAnythings()))
            ;

但在那之后我有点卡住了。

最佳答案

除非我弄错了,否则你不能一次性完成这两种操作。但由于它们彼此独立(Something 中的 Anythings 中的 nothings 之和与它们的顺序无关),因此没关系。只需一个接一个地排序即可。

要按 NoThingsSomethings 内的 Anytings 进行排序:

mySomethings.stream().map(Something::getAnythings)
            .forEach(as -> as.sort(Comparator.comparing(Anything::getNoThings)
                                             .reversed()));

要按 AnythingsnoThings 总和对 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/

相关文章:

java - 如何在不使用 Jackson Api 的情况下在 Java 中将字符串转换为列表<String>

r - 如何在 geom_point 点图中仅显示前 10 个类别和值?

java - 为什么我在 STS 中遇到编译错误

linux - 运行 .Jar 需要 Java 7 或 8 (Linux)

java - ArrayList 包含来自另一个 ArrayList 的一个或多个实体

java - Spring Boot 1.4 测试 : Configuration error: found multiple declarations of @BootstrapWith

java - 我们如何为 TextView 中的所有单词设置可点击?

java - 依赖项的测试资源不在类路径中?

php - 为什么 SORT_REGULAR 在 PHP 中产生不一致的结果?

python - 在 Python 中按不同级别排序