You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Java Lambda分组ArrayList元素并解决JSON字段缺失异常

解决Java中按price和side分组JSONObject并求和shares的问题

你遇到的这个JSONException问题其实很典型——咱们先揪出根源:你用reduce合并元素的时候,每次生成的新JSONObject h只存了price和对应的buyShares/sellShares,完全没保留side字段。等下一轮reduce执行时,f1就是这个没有side的中间对象,再调用f1.get("side")自然就会抛出找不到字段的异常了。

换个更稳妥的思路解决问题

与其在reduce里反复处理中间对象的字段缺失问题,不如直接对每个price分组里的元素,分别统计买入和卖出的shares总和,逻辑更清晰,也不会踩字段缺失的坑。

下面是修正后的代码:

ArrayList<JSONObject> aOrdersArray = new ArrayList<>(aOrders.values());
System.out.println(aOrdersArray);

List<JSONObject> test = aOrdersArray.stream()
    // 按price字符串分组(原数据里price是字符串类型,用getString更准确)
    .collect(Collectors.groupingBy(json -> json.getString("price")))
    .entrySet().stream()
    .map(entry -> {
        String price = entry.getKey();
        int buyTotal = 0;
        int sellTotal = 0;
        
        // 遍历当前price分组下的所有订单,累加买入/卖出数量
        for (JSONObject order : entry.getValue()) {
            String side = order.getString("side");
            int shares = order.getInt("shares");
            if ("B".equals(side)) {
                buyTotal += shares;
            } else if ("S".equals(side)) {
                sellTotal += shares;
            }
        }
        
        // 组装结果JSONObject,仅添加有值的字段
        JSONObject result = new JSONObject();
        result.put("price", price);
        if (buyTotal > 0) {
            result.put("buyShares", buyTotal);
        }
        if (sellTotal > 0) {
            result.put("sellShares", sellTotal);
        }
        return result;
    })
    .collect(Collectors.toList());

System.out.println(test);

额外注意的细节

  1. 原代码里的distinct()如果没有完全重复的订单(所有键值对都一致的情况),其实是多余的,可以去掉;
  2. 原数据中的price是字符串类型,分组时用getString("price")比getInt("price")更安全——如果后续price出现带小数的字符串(比如"500.5"),getInt会直接抛出异常。

这个方案运行后,就能得到你期望的输出结果,而且不会再出现字段缺失的异常啦~

内容的提问来源于stack exchange,提问作者BOUK.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:23:15