我尝试按java数组列表元素分组。
我有一个jsonobjects数组,如下所示,我想按price和side字段分组,然后用new fileds buyshares和sellshares对股票进行求和
[{"shares":20,"side":"B","orderId":"001","price":"500"},
{"shares":20,"side":"S","orderId":"002","price":"501"},
{"shares":25,"side":"B","orderId":"003","price":"500"},
{"shares":10,"side":"S","orderId":"004","price":"501"},
{"shares":30,"side":"B","orderId":"005","price":"505"},
{"shares":35,"side":"B","orderId":"006","price":"505"},
{"shares":35,"side":"S","orderId":"007","price":"500"}]
我想按价格和侧面进行分组,得到如下结果:
[{"price":"500","buyShares":45, "sellShares":35}, {"sellShares":30,"price":"501"}, {"price":"505","buyShares":65}]
我使用以下java代码:
ArrayList<JSONObject> aOrdersArray = new ArrayList<>(aOrders.values());
System.out.println(aOrdersArray);
List<JSONObject> test = aOrdersArray.stream()
.distinct()
.collect(Collectors.groupingBy(jsonObject -> jsonObject.getInt("price")))
.entrySet().stream()
.map(e -> e.getValue().stream()
.reduce((f1,f2) -> {
JSONObject h = new JSONObject();
h.put("price",f1.get("price"));
System.out.println(f1);
if (f1.get("side").equals("B") && f2.get("side").equals("B")) {
h.put("buyShares", f1.getInt("shares") + f2.getInt("shares"));
}
else if (f1.get("side").equals("S") && f2.get("side").equals("S")) {
h.put("sellShares", f1.getInt("shares") + f2.getInt("shares"));
}
else if (f1.get("side").equals("S")) {
h.put("sellShares", f1.get("shares"));
}
else if (f1.get("side").equals("B")) {
h.put("buyShares",f1.get("shares"));
}
else if (f2.get("side").equals("S")) {
h.put("sellShares", f2.get("shares"));
}
else if (f2.get("side").equals("B")) {
h.put("buyShares",f2.get("shares"));
}
return h;
}))
.map(f -> f.get())
.collect(Collectors.toList());
System.out.println(test);
我有时会犯以下错误
Exception in thread "main" org.json.JSONException: JSONObject["side"] not found.
3条答案
按热度按时间0s7z1bwu1#
你要做的事情很复杂而且容易出错,因为你开始的时候走错了路。
你不应该有一个
JSONObject
首先。json输入中的数据是常规的,您希望对其内容进行操作。正确的方法是创建一个表示这样一个记录的java对象,然后将json输入转换成一个适当的、惯用的java版本。你想要:
注意:使用Lombok山的
@Value
. 假设这个东西有一个构造函数,所有字段都是final,tostring和equals以及hashcode都在正确的位置,等等。一旦有了上述两种类型,就可以将输入的json转换为
List<Record>
. 用这个武装起来List<Record>
,然后,也只有这样,你才能开始走Map、分组等道路。当然,这个错误将永远不会发生,并且您的Map/组代码将更易于阅读。任何输入错误都会导致编译时错误。自动完成将工作良好,等等:所有的优势。
要将json转换为给定类型,请使用jackson。如果你只是不想添加依赖项(你应该,真的),那么写一个
public static Record fromJson(JSONObject)
方法,并使用.map(Record::fromJson)
立即访问记录对象流,再也不返回jsonobject。您的代码现在非常容易阅读,所有方法都有专有名称(它是
getBuyShares()
,不是.getInt("buyShares")
)可通过自动完成等方式发现,例如,您可以单独测试merge
功能。mpbci0fu2#
虽然每个人都建议使用对象Map值来简化计算,但这本身并不是必须的。我能想到的原因是:
您需要为每一种合理类型的json节点创建一个Map(虽然在某种程度上它可以自动化)——如果您的Map在您的代码库中被广泛使用,那么这是完全正确的,但是可能(!)不值得为临时做一次在用的东西;
直接操作json树可以保证绑定(反序列化)不会影响原始的json树结构(即在gson中(很可能是在jackson中),可以实现一个类型适配器,它不能保证数据Map的完美往返:in json->mappings->out json=>in json!=输出json;对json和back的Map也是如此);
一些json库(就像你的一样?)根本不提供对象Map/绑定特性。
e3bfsja23#
要使用gson,可以创建一个类:
然后您可以使用这个从jsonMap对象: