如何用Java 8 Lambda与Stream处理含不同键的JSONObject及JSONArray
用Java 8 Stream + Lambda重构JSON遍历代码
需求说明
刚接触Java 8 Lambda,希望把遍历JSONArray生成指定字段JSONObject的for循环代码,改成用Lambda和Stream实现。具体需求是:接收包含学生信息的JSONArray,生成两个JSONObject——一个以language为键、name为值,另一个以language为键、section为值。
示例输入
"students": [ { "name": "tom", "section": "A", "language": "english" }, { "name": "john", "section": "B", "language": "dutch" }, { "name": "sam", "section": "C", "language": "spanish" } ]
预期输出
nameJson : {"english":"tom","dutch":"john","spanish":"sam"} sectionJson: {"english":"A","dutch":"B","spanish":"C"}
现有for循环实现
JSONArray notification = json.optJSONArray("studentData"); JSONObject nameJson = new JSONObject(); JSONObject sectionJson = new JSONObject(); for (int i = 0; i < notification.length(); i++) { nameJson.put( notification.getJSONObject(i).get("language").toString(), notification.getJSONObject(i).get("name").toString() ); sectionJson.put( notification.getJSONObject(i).get("language").toString(), notification.getJSONObject(i).getString("section").toString() ); }
Stream + Lambda重构方案
由于JSONArray本身不支持直接转成Stream,我们可以通过索引流遍历元素,结合Collectors.toMap收集键值对,最后用JSONObject的Map构造器生成目标对象。
基础实现
JSONArray notification = json.optJSONArray("studentData"); // 生成nameJson JSONObject nameJson = new JSONObject( IntStream.range(0, notification.length()) .mapToObj(notification::getJSONObject) .collect(Collectors.toMap( obj -> obj.getString("language"), obj -> obj.getString("name") )) ); // 生成sectionJson JSONObject sectionJson = new JSONObject( IntStream.range(0, notification.length()) .mapToObj(notification::getJSONObject) .collect(Collectors.toMap( obj -> obj.getString("language"), obj -> obj.getString("section") )) );
优化复用版
如果需要多次转换不同字段,可以抽取通用方法减少重复代码:
// 通用转换方法 private static JSONObject convertToJSON(JSONArray array, Function<JSONObject, String> keyExtractor, Function<JSONObject, String> valueExtractor) { return new JSONObject( IntStream.range(0, array.length()) .mapToObj(array::getJSONObject) .collect(Collectors.toMap(keyExtractor, valueExtractor)) ); } // 调用示例 JSONArray notification = json.optJSONArray("studentData"); JSONObject nameJson = convertToJSON(notification, obj -> obj.getString("language"), obj -> obj.getString("name")); JSONObject sectionJson = convertToJSON(notification, obj -> obj.getString("language"), obj -> obj.getString("section"));
代码说明
IntStream.range(0, notification.length()):生成从0到数组长度-1的索引流,模拟for循环的索引遍历逻辑mapToObj(notification::getJSONObject):将每个索引转换为对应的JSONObject对象Collectors.toMap(...):把每个JSONObject的指定字段作为键值对,收集成Map<String, String>new JSONObject(Map):利用JSONObject的构造器直接将Map转换为目标JSON对象
内容的提问来源于stack exchange,提问作者sowmya
相关产品推荐
相关产品推荐

