将一个对象值列表转换为分组

3
我有以下这段代码。
OrderCriteria o1 = new OrderCriteria(1, 1, 101, 201);
OrderCriteria o2 = new OrderCriteria(1, 1, 102, 202);
OrderCriteria o4 = new OrderCriteria(1, 1, 102, 201);
OrderCriteria o5 = new OrderCriteria(2, 2, 501, 601);
OrderCriteria o6 = new OrderCriteria(2, 2, 501, 602);
OrderCriteria o7 = new OrderCriteria(2, 2, 502, 601);
OrderCriteria o8 = new OrderCriteria(2, 2, 502, 602);
OrderCriteria o9 = new OrderCriteria(2, 2, 503, 603);

需要翻译的内容:

OrderCriteria 是指如下形式:

public class OrderCriteria {
    private final long orderId;
    private final long orderCatalogId;
    private final long procedureId;
    private final long diagnosisId;

    public OrderCriteria(long orderId, long orderCatalogId, long procedureId, long diagnosisId) {
        this.orderId = orderId;
        this.orderCatalogId = orderCatalogId;
        this.procedureId = procedureId;
        this.diagnosisId = diagnosisId;
    }

    // Getters
}

我希望能够获取按订单号分组的程序列表和诊断列表。因此,它应该返回以下内容:
{1, {101, 102}, {201, 202}}
{2, {501, 502, 503}, {601, 602, 603}}

这意味着编号为1的订单具有101、102等过程编号和201、202等诊断编号。我尝试使用Google Guava表格,但没有找到有效的解决方案。
2个回答

0
首先,您需要一个新的结构来保存分组数据:
class OrderCriteriaGroup {
    final Set<Long> procedures = new HashSet<>();
    final Set<Long> diagnoses = new HashSet<>();

    void add(OrderCriteria o) {
        procedures.add(o.getProcedureId());
        diagnoses.add(o.getDiagnosisId());
    }

    OrderCriteriaGroup merge(OrderCriteriaGroup g) {
        procedures.addAll(g.procedures);
        diagnoses.addAll(g.diagnoses);
        return this;
    }
}

add()merge()是方便的方法,可以帮助我们流式收集数据,就像这样:

Map<Long, OrderCriteriaGroup> grouped = criteriaList.stream()
        .collect(Collectors.groupingBy(OrderCriteria::getOrderId,
                Collector.of(
                        OrderCriteriaGroup::new,
                        OrderCriteriaGroup::add,
                        OrderCriteriaGroup::merge)));

我尝试使用以上解决方案,但是遇到编译错误,提示“Collector”中的“of(Supplier<R>,BiConsumer<R,T>,BinaryOperator<R>,Collector.Characteristics ...)”方法不适用于参数(OrderCriteriaGroup::new,OrderCriteriaGroup::add,OrderCriteriaGroup::merge)。 - StonecoldIM
@StonecoldIM,有一个小的拼写错误,但现在对我来说它可以工作了:https://ideone.com/L0ihmk - shmosel
非常感谢您,shmosel。上帝保佑您,先生。非常感激。这对我有用,将对我继续进行当前工作非常有帮助。祝您有美好的一天。 - StonecoldIM

0

我强烈建议您更改输出结构。根据您的示例,当前可能是Map<List<Set<Long>>>。我建议您使用以下结构区分"procedure:"diagnosis"数据集:

Map<Long, Map<String, Set<Long>>> map = new HashMap<>();

现在填充数据非常容易:

for (OrderCriteria oc: list) {
     if (map.containsKey(oc.getOrderId())) {
        map.get(oc.getOrderId()).get("procedure").add(oc.getProcedureId());
        map.get(oc.getOrderId()).get("diagnosis").add(oc.getDiagnosisId());
     } else {
        Map<String, Set<Long>> innerMap = new HashMap<>();
        innerMap.put("procedure", new HashSet<>());
        innerMap.put("diagnosis", new HashSet<>());
        map.put(oc.getOrderId(), innerMap);
     }
}

输出:{1={诊断=[201,202],过程=[102]},2={诊断=[601,602,603],过程=[501,502,503]}}


如果您坚持使用您起草的结构,那么您需要记住第一个Set包含程序,第二个Set包含诊断,而维护将是不切实际的。

Map<Long, List<Set<Long>>> map = new HashMap<>();   

for (OrderCriteria oc: list) {
     if (map.containsKey(oc.getOrderId())) {    
        map.get(oc.getOrderId()).get(0).add(oc.getProcedureId());
        map.get(oc.getOrderId()).get(1).add(oc.getDiagnosisId());
     } else {
        List<Set<Long>> listOfSet = new ArrayList<>();
        listOfSet.add(new HashSet<>());
        listOfSet.add(new HashSet<>());
        map.put(oc.getOrderId(), listOfSet);
     }
}

输出:{1=[[102],[201,202]],2=[[501,502,503],[601,602,603]]}


或者你可能想要创建一个新的对象,使用2个Set<Long>来存储数据(另一个答案展示了方法)。


非常接近我所寻找的内容,但由于某种原因,在这里过滤了101号程序。 - StonecoldIM

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