您的位置:首页 > 编程语言 > Java开发

解决问题之道--使用Java实现数据的分组求和

2014-12-18 12:31 726 查看
今天碰到了这样一个问题,说的是有类似这样的JSON对象

var responseData= {responseModuleData:[
{
"branch_name": "网点1",
"bra_id": "043900010001000100010002",
"dev_type": "农村",
"fault_desc": "流水纸",
"duration": "10",
"total_count": "10"
},
{
"branch_name": "网点1",
"bra_id": "043900010001000100010002",
"dev_type": "农村",
"fault_desc": "流水纸",
"duration": "10",
"total_count": "10"
},
{
"branch_name": "网点2",
"bra_id": "043900010001000100010002",
"dev_type": "县",
"fault_desc": "IC卡",
"duration": "15",
"total_count": "20"
},
{
"branch_name": "网点3",
"bra_id": "043900010001000100010002",
"dev_type": "市",
"fault_desc": "IC卡",
"duration": "11",
"total_count": "12"
}
]};


我要对里面的数据进行分组计算,比如当我想要按照branch_name不同来分组,分别计算duration和total_count的和,或者按照branch_name和bra_id两个的值进行分组计算。如果就这个JSON对象来说,加入我明确的知道是按照branch_name,dey_type和fault_desc进行分组,分别求duration的值和total_count的值的话,可以进行这样来做,先把JSON对象转化为一个JSONArray数组,这里的key的值是"responseModuleData"之类的元素的Key的值
JSONArray re_dt = (JSONArray) (responseData.get(key)==null?new JSONArray():responseData.get(key));
int startindex = 0;
if (re_dt.isEmpty() && re_dt.size()>0) {
JSONArray list = (JSONArray) (responseData.get(key) == null ? null : responseData.get(key));
if (list != null) {
re_dt.add(list);
}
} else {
startindex = 1;
}
////当dataJSON的length的值是1的是后因为在SQL里面已经进行过对应的group,sum等操作了,
//所以就不需要在一次的分组计算了,只需要和另外的work返回的值进行计算
for(int i = startindex;i<dataJson.length;i++){
responseData = JSONObject.fromObject(dataJson[i]);
JSONArray list = (JSONArray) (responseData.get(key) == null ? null : responseData.get(key));
if (list != null && list.size()>0) {
//把第二个数组中对应的元素数组的每一个元素与之前的数组中的元素进行一一的比较,相同的进行求和,不同的把数据加入到第一个的元素数组中
for(int h=0;h<list.size();h++){
JSONObject jo = (JSONObject) list.get(h);
String bra_id= jo.getString("bra_id");
String dev_type=jo.getString("dev_type");
String desc = null;
if(key.equals("responseModelData"))
desc = jo.getString("fault_desc");
String du = jo.getString("duration");
String to =  jo.getString("total_count");
int o = -1;
String duration = null;
String total_count= null;
for(int j=0;j<re_dt.size();j++){
JSONObject job = (JSONObject) re_dt.get(j);
if(key.equals("responseModelData")){
if(job.getString("bra_id").equals(bra_id)
&&job.getString("dev_type").equals(dev_type)
&&job.getString("fault_desc").equals(desc)){
o=j;
duration=job.getString("duration");
total_count=job.getString("total_count");
break;
}
}
}
}
if(o>=0){
JSONObject re = (JSONObject)re_dt.get(o);
if(duration!=null)
re.put("duration",
Integer.parseInt(du)+Integer.parseInt(duration));
if(total_count!=null)
re.put("total_count",
Integer.parseInt(to)+Integer.parseInt(total_count));
}else{
re_dt.add(jo);
}
}
}
}


针对上面的需求情况,以及已知对应的数据编写的相应的代码,如果我们不知道responseModuleData中元素的名称,个数,也不知道要分组的元素是那几个,还不知道究竟是要求那几个元素的和的话,我们如何编写一个公共的方法呢?

我的做法是把responseModuleData的元素做成一个hashMap都传进去,map的Key值会有一定的规律,比如使用"v0,v1,v2...."这样的值,value是对应的元素的名称,在把分组的元素的个数,和求和元素的个数分别传过去,它们两个的元素的位置分别占在map集合的最前部和最后部,这样我们就可以通过循环知道分组的和求和的元素究竟是什么了,这样我编写了如下的代码

JSONArray re_dt = (JSONArray) (responseData.get(key)==null?new JSONArray():responseData.get(key));
int startindex = 0;
if (re_dt.isEmpty() && re_dt.size()>0) {
JSONArray list = (JSONArray) (responseData.get(key) == null ? null : responseData.get(key));
if (list != null) {
re_dt.add(list);
}
} else {
startindex = 1;
}
for(int i = startindex;i<dataJson.length;i++){
responseData = JSONObject.fromObject(dataJson[i]);
JSONArray list = (JSONArray) (responseData.get(key) == null ? null : responseData.get(key));
if (list != null && list.size()>0) {
for(int h=0;h<list.size();h++){
JSONObject jo = (JSONObject) list.get(h);
String[] strings = new String[param.size()];
String[] ones = new String[grnum];
//获取元素的数组中的其中的某一个对象的所有的元素的信息
for (int j = 0; j < param.size(); j++) {
strings[j] = jo.getString(param.get("var" + j).toString());
}
//对应的要求和的元素的初始化
for (int j = 0; j < sunum; j++) {
ones[j] = 0;
}
int flag = param.size() - grnum;
int o = -1;
for(int j=0;j<re_dt.size();j++){
JSONObject job = (JSONObject) re_dt.get(j);
switch (grnum) {
case 1:
if (job.getString((String)param.get("var0")).equals(strings[0])) {
o=j;
//当有对应
for (int k = 0; k < sunum; k++) {
ones[k] =
job.getString((String)param
.get("var" + (param.size() - sunum +k)));
}
}
break;
case 2:
if (job.getString((String)param.get("var0")).equals(strings[0])&&
job.getString((String)param.get("var1")).equals(strings[1])) {
o=j;
for (int k = 0; k < sunum; k++) {
ones[k] = job.getString((String)param
.get("var" + (param.size() - sunum +k)));
}
}
break;
.........
default:
break;
}
}
if(o>=0){
JSONObject re = (JSONObject)re_dt.get(o);
for (int k = 0; k < sunum; k++) {
if (ones[k] != null) {
re.put((String)param.get("var"+(param.size() - sunum + k)),
Integer.parseInt(strings[param.size() - sunum + k])
+Integer.parseInt(ones[k]));
}
}
}else{
re_dt.add(jo);
}
}
}
}


问题就出在使用switch上,因为不知道究竟有多少个要求相等的元素的个数,所以使用的是通过判断元素的个数进行选择,这样永远不可能避免出现例外的情况,因为我不知道grnum的值最大值是多少,只能根据自己的经验判断一般不超过六个,这样段代码在先天上就要保证传入的grnum的值不能大于六如果大于的话,计算的结果肯定不正确,最好的办法是使用for循环做这件事,但是显然直接使用for循环是无法解决这个问题的。

写完之后就放那了,过了一段时间,脑袋冷静下来在去想这个问题的时候,我突然发现自己是被自己给陷进去了,既然正面直接使用foe循环无法解决问题,为什么我不能从反面入手呢,于是我就把switch改为:

boolean temp = true;
for (int k = 0; k < grnum; k++) {
if (!job.getString((String)param.get("var" + k)).equals(strings[k])) {
temp = false;
}
}
if (temp) {
o=j;
for (int k = 0; k < sunum; k++) {
ones[k] = job.getString((String)param
.get("var" + (param.size() - sunum +k)));
}
}


这样就完全解决了问题。

这是一个很简单的事情,但是有的时候由于固定思维的缘故,却把解决问题的办法整的特别的复杂。有时候自己真的是应该多想想,尤其是变换角度的思考问题,能要比多动手要强一些。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐