如何用Java Lambda分组ArrayList元素并解决JSON字段缺失异常
你遇到的这个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);
额外注意的细节
- 原代码里的
distinct()如果没有完全重复的订单(所有键值对都一致的情况),其实是多余的,可以去掉; - 原数据中的
price是字符串类型,分组时用getString("price")比getInt("price")更安全——如果后续price出现带小数的字符串(比如"500.5"),getInt会直接抛出异常。
这个方案运行后,就能得到你期望的输出结果,而且不会再出现字段缺失的异常啦~
内容的提问来源于stack exchange,提问作者BOUK.
相关产品推荐
相关产品推荐

