Java 8:按多个字段分组,然后根据值排序

3

我有一个称为 Info 的类

public class Info {
    private String account;
    private String opportunity;
    private Integer value;
    private String desc;
}

我想要将一组Info根据两个字段(先按账户再按机会)进行分组,并根据其值进行排序。即:

在分组和排序之前的信息列表:

List<Info> infos = [(account = 1234, opportunity = abs, value = 4, desc= test),
(account = 1234, opportunity = abs, value = 5, desc = testing),
(account = 1234, opportunity = abss, value = 10, desc = vip),
(account = 123, opportunity = abss, value = 8, desc = vip),
(account = 12, opportunity = absddd, value = 4, desc = production),
(account = 12, opportunity = absooo, value = 2, desc = test)]

在分组和排序后,我期望的结果是:

Map<String, Map<String, List<Info>>> result = {
    1234 = {
        abss = [(account = 1234, opportunity = abss, value = 10, desc = vip)],
        abs = [(account = 1234, opportunity = abs, value = 5, desc = testing),  
               (account = 1234, opportunity = abs, value = 4, desc = test)]
    },
    123 = {
        abss = [(account = 123, opportunity = abss, value = 8, desc = vip)]
    },
    12 = {
        absddd = [(account = 12, opportunity = absddd, value = 4, desc = production)],
        absooo = [(account = 12, opportunity = absooo, value = 2, desc = test)]
    }
}

o/p是基于值排序的(10->(5+4)->8->4->2)

我尝试了如下代码= infos.stream().collect(Collectors.groupingBy(Info::getAccount, Collectors.groupingBy(r -> r.getOpportunity(), Collectors.toList()))), 但它的排序是随机的。


你目前尝试了什么? - Ravindra Ranwala
Info.stream().collect(Collectors.groupingBy(Info::getAccount, Collectors.groupingBy(r -> r.getOpportunity(), Collectors.toList()))) 但是它的排序是随机的。 - wasim sarkar
请将其添加到您的问题中。 - Ravindra Ranwala
1
更新了问题部分。 - wasim sarkar
1个回答

3

按照 Infovalue 进行排序:

  1. 通过比较 value,使流 sorted,以便按顺序执行分组。
  2. 在调用groupingBy时,指定mapFactory中的LinkedHashMap以保留插入顺序。

以下程序演示了如何实现。


import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Info {
    private String account;
    private String opportunity;
    private Integer value;
    private String desc;

    private Info(String account, String opportunity, Integer value, String desc) {
        super();
        this.account = account;
        this.opportunity = opportunity;
        this.value = value;
        this.desc = desc;
    }

    public static void main(String[] args) {
        List<Info> infos = new ArrayList<>();
        infos.add(new Info("12", "absddd", 4, "production"));
        infos.add(new Info("1234", "abss", 10, "vip"));
        infos.add(new Info("1234", "abs", 4, "test"));
        infos.add(new Info("1234", "abs", 5, "testing"));
        infos.add(new Info("123", "abss", 8, "vip"));
        infos.add(new Info("12", "absooo", 2, "test"));
        Map<String, Map<String, List<Info>>> sortedResult = infos.stream().sorted(Info::compareByValueDesc)
                .collect(Collectors.groupingBy(Info::getAccount, LinkedHashMap::new,
                        Collectors.groupingBy(r -> r.getOpportunity(), LinkedHashMap::new, Collectors.toList())));
        sortedResult.forEach((key, value) -> System.out.println(key + value.toString()));
    }

    public static int compareByValueDesc(Info other1, Info other2) {
        return -other1.value.compareTo(other2.value);
    }

    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    public String getOpportunity() {
        return opportunity;
    }

    public void setOpportunity(String opportunity) {
        this.opportunity = opportunity;
    }

    public String toString() {
        return this.value.toString();
    }
}

谢谢回复。但是我在尝试满足以下输入时遇到了问题: `infos.add(new Info("12", "absddd", 4, "production")); infos.add(new Info("1234", "abss", 11, "vip")); infos.add(new Info("12345", "abs", 4, "test")); infos.add(new Info("12345", "abs", 5, "testing")); infos.add(new Info("123", "abss", 8, "vip")); infos.add(new Info("12", "absooo", 2, "test"));`在这种情况下,输出结果为 1234{abss=[11]} 123{abss=[8]} 12345{abs=[5, 4]} 12{absddd=[4], absooo=[2]}; 这不是排序的。 - wasim sarkar
你对这种情况有什么期望?我是否漏掉了任何标准(在我看来似乎是正确的)? - samabcde
我想根据groupingby和summingLong对其进行排序,在上面的评论中,我提到了输入,其输出应为1234{abss=[11]} 12345{abs=[5, 4]} 123{abss=[8]} 12{absddd=[4], absooo=[2]} - wasim sarkar
看起来我误解了您的需求,建议您编辑帖子提供以下顺序:1.账户组条目,2.机会组条目,3.机会组中的值。 - samabcde
真的,我正在尝试不同的过程,但无法通过嵌套映射获取所需的内容。 - wasim sarkar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接