解决问题之道--使用Java实现数据的分组求和
2014-12-18 12:31
726 查看
今天碰到了这样一个问题,说的是有类似这样的JSON对象
我要对里面的数据进行分组计算,比如当我想要按照branch_name不同来分组,分别计算duration和total_count的和,或者按照branch_name和bra_id两个的值进行分组计算。如果就这个JSON对象来说,加入我明确的知道是按照branch_name,dey_type和fault_desc进行分组,分别求duration的值和total_count的值的话,可以进行这样来做,先把JSON对象转化为一个JSONArray数组,这里的key的值是"responseModuleData"之类的元素的Key的值
针对上面的需求情况,以及已知对应的数据编写的相应的代码,如果我们不知道responseModuleData中元素的名称,个数,也不知道要分组的元素是那几个,还不知道究竟是要求那几个元素的和的话,我们如何编写一个公共的方法呢?
我的做法是把responseModuleData的元素做成一个hashMap都传进去,map的Key值会有一定的规律,比如使用"v0,v1,v2...."这样的值,value是对应的元素的名称,在把分组的元素的个数,和求和元素的个数分别传过去,它们两个的元素的位置分别占在map集合的最前部和最后部,这样我们就可以通过循环知道分组的和求和的元素究竟是什么了,这样我编写了如下的代码
问题就出在使用switch上,因为不知道究竟有多少个要求相等的元素的个数,所以使用的是通过判断元素的个数进行选择,这样永远不可能避免出现例外的情况,因为我不知道grnum的值最大值是多少,只能根据自己的经验判断一般不超过六个,这样段代码在先天上就要保证传入的grnum的值不能大于六如果大于的话,计算的结果肯定不正确,最好的办法是使用for循环做这件事,但是显然直接使用for循环是无法解决这个问题的。
写完之后就放那了,过了一段时间,脑袋冷静下来在去想这个问题的时候,我突然发现自己是被自己给陷进去了,既然正面直接使用foe循环无法解决问题,为什么我不能从反面入手呢,于是我就把switch改为:
这样就完全解决了问题。
这是一个很简单的事情,但是有的时候由于固定思维的缘故,却把解决问题的办法整的特别的复杂。有时候自己真的是应该多想想,尤其是变换角度的思考问题,能要比多动手要强一些。
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))); } }
这样就完全解决了问题。
这是一个很简单的事情,但是有的时候由于固定思维的缘故,却把解决问题的办法整的特别的复杂。有时候自己真的是应该多想想,尤其是变换角度的思考问题,能要比多动手要强一些。
相关文章推荐
- 使用apache的TelnetClient实现java向telnet服务器发送命令并显示数据(解决乱码问题)
- java实现EXCEL数据导入到数据库中的格式问题的解决
- C++编程笔记:使用WinHTTP实现HTTP访问(解决接收UTF8数据乱码问题)
- C#调用exe解决PDF转图片问题(使用PDFBox方案,java语言编译jar包实现)
- 使用JqGrid列表数据分组显示问题的解决方法
- 解决在java的ssm框架中使用ajax提交数据遇到的跨域问题
- 使用asx3m与xstream配合解决flex与java利用httpservice传递xml数据问题
- 使用asx3m与xstream配合解决flex与java利用httpservice传递xml数据问题
- 使用Tomcat实现Java连接池(解决main中不能够调用问题)
- java使用POI解析Excel表格中由纯数字组成的字符串报错问题&解决数据自动保存为科学计数法问题
- 使用java实现多种方式解决图片压缩的问题
- Java解决TopK问题(使用集合和直接实现)
- JAVA学习13_line.split("")的使用和解决ES接收数据不全的问题
- java爬虫问题二: 使用jsoup爬取数据class选择器中空格多选择怎么解决
- 使用asx3m与xstream配合解决flex与java利用httpservice传递xml数据问题
- java爬虫问题二: 使用jsoup爬取数据class选择器中空格多选择怎么解决
- Java解决TopK问题(使用集合和直接实现)
- C++编程笔记:使用WinHTTP实现HTTP访问(解决接收UTF8数据乱码问题)
- 使用Spring实现异常统一处理【三】--java.lang.IllegalStateException: STREAM问题的解决
- [java]增删改查后给出操作提示后跳转到数据列表的小问题解决[简单实现]