JAVA 实现大批量数据的分组统计



package com.xxx;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
*
* 使用demo
*
* group(data,new String[]{"code","name"},new String[]{"amount","quantity"},new String[][]{{"amount","avgAmount"},{"quantity","avgQuantity"}},"");
* 以上例子为
* 按code,name分组,sum amount,quantity两个字段 以及计算quantity,amount的平均值生成的对应的字段为avgAmount,avgQuantity
* 需要注意的是 计算平均的字段必须计算合计 即avgFields中的内容必须包函在sumFields中
*
*
* 测试用例
* DataUtils test = new DataUtils();
List<Map<String,Object>> data= new ArrayList<Map<String,Object>>();
Map<String,Object> map = new HashMap<String,Object>();
map.put("code", "001");
map.put("name", "test");
map.put("quantity", "20");
map.put("amount", "100");
map.put("price", "5");
data.add(map);
map = new HashMap<String,Object>();
map.put("code", "001");
map.put("name", "test");
map.put("quantity", "10");
map.put("amount", "200");
map.put("price", "20");
data.add(map);
map = new HashMap<String,Object>();
map.put("code", "002");
map.put("name", "test1");
map.put("quantity", "10");
map.put("amount", "200");
map.put("price", "20");
data.add(map);
map = new HashMap<String,Object>();
map.put("code", "003");
map.put("name", "test1");
map.put("quantity", "10");
map.put("amount", "200");
map.put("price", "20");
data.add(map);
List<Map<String,Object>> result = test.group(data,new String[]{"code","name"},new String[]{"amount","quantity"},new String[][]{{"amount","avgAmount"},{"quantity","avgQuantity"}},"");

* @author 461245
*
*
*/
public class DataUtils {

private String keyValueSplitChar= "=";
private String filedSplitChar= "|";
/**
* 分组函数
*
* @param groupFields
* 分组字段
* @param sumFields 
* 合计字段
* @param avgFields
* 平均值字段
* @return
*/
public List<Map<String,Object>> group(List<Map<String,Object>> datas,String[] groupFields,String[] sumFields,String[][] avgFields){
return group(datas,groupFields,sumFields,avgFields,null);
}

/**
* 分组函数
*
* @param groupFields
* 分组字段
* @param sumFields 
* 合计字段
* @param avgFields
* 平均值字段
* @param countField
* 分组后的count新字段
* @return
*/
public List<Map<String,Object>> group(List<Map<String,Object>> datas,String[] groupFields,
String[] sumFields,String[][] avgFields,String countField){
Map<String,Object> temp = new HashMap<String,Object>();
for (Map<String,Object> data : datas) {
String groupFieldKey = "";
for (String groupField : groupFields) {
//code_name_ 即 code_001|name_test| code_003|name_test1|
groupFieldKey+=groupField+getKeyValueSplitChar()+data.get(groupField)+getFiledSplitChar();
}
//算分组合计
if(sumFields!=null)
groupSum(sumFields, temp, data, groupFieldKey);
//统计分组行数
if(countField!=null)
countField = groupCount(countField, temp, groupFieldKey);
//计算平均
if(avgFields!=null)
groupAvg(avgFields, countField, temp, groupFieldKey);
}
//转换结果
List<Map<String, Object>> results = covertResult(temp);
return results;
}

private void groupAvg(String[][] avgFields, String countField,
Map<String, Object> temp, String groupFieldKey) {
for (int i = 0; i < avgFields.length; i++) {
for (int j = 0; j < avgFields.length; j++) {
double value = (Double) temp.get(groupFieldKey+avgFields[i][0]);
int count = (Integer) temp.get(groupFieldKey+countField);
temp.put(groupFieldKey+avgFields[i][1], value/count);
}
}
}

/**
* 统计分组后的条数
* @param countField
* @param temp
* @param groupFieldKey
*/
private String groupCount(String countField, Map<String, Object> temp,
String groupFieldKey) {
if(countField == null || countField.trim().equals(""))countField = "&count";
String countFieldKey = groupFieldKey+countField;
if(temp.containsKey(countFieldKey)){
temp.put(countFieldKey, Integer.parseInt(temp.get(countFieldKey).toString())+1);
}else{
temp.put(countFieldKey, 1);
}
return countField;
}

/**
* 将temp中的key value 转换为List<Map<String,Object>>对像
* @param temp
* @return
*/
private List<Map<String, Object>> covertResult(Map<String, Object> temp) {
Map<String,Object> values = new HashMap<String,Object>();
for (String key : temp.keySet()) {
if(!values.containsKey(key.substring(0, key.lastIndexOf(getFiledSplitChar())))){
//code_001|name_test|quantity_10
values.put(key.substring(0, key.lastIndexOf(getFiledSplitChar())), key+getKeyValueSplitChar()+temp.get(key));
continue;
}
for (String rk : values.keySet()) {
if(key.startsWith(rk)){
//code_001|name_test|quantity_10|amount_20
values.put(rk, values.get(rk)+key.substring(key.lastIndexOf(getFiledSplitChar()))+getKeyValueSplitChar()+temp.get(key));
break;
}
}
}
List<Map<String,Object>> results = new ArrayList<Map<String,Object>>();
Map<String,Object> result;
for (Object key : values.values()) {
result = new HashMap<String,Object>();
String ss[] = key.toString().split("\\"+getFiledSplitChar());
for (String t : ss) {
String[] ts = t.split("\\"+getKeyValueSplitChar());
result.put(ts[0], ts[1]);
}
results.add(result);
}
return results;
}

/**
* 计算合计
* @param sumFields
* @param temp
* @param data
* @param groupFieldKey
*/
private void groupSum(String[] sumFields, Map<String, Object> temp,
Map<String, Object> data, String groupFieldKey) {
for (String sumField : sumFields) {
String groupFieldKey_sumField = groupFieldKey+sumField;
//code_name_quantity code_name_amount
//即code_001|name_test|quantity code_001|name_test|amount code_003|name_test1|amount
if(temp.containsKey(groupFieldKey_sumField)){
temp.put(groupFieldKey_sumField, Double.parseDouble(data.get(sumField).toString())+Double.parseDouble(temp.get(groupFieldKey_sumField).toString()));
}else{
temp.put(groupFieldKey_sumField, Double.parseDouble(data.get(sumField).toString()));
}
}
}

public static void main(String[] args) {
DataUtils test = new DataUtils();
List<Map<String,Object>> data= new ArrayList<Map<String,Object>>();
Map<String,Object> map = new HashMap<String,Object>();
map.put("code", "001");
map.put("name", "test");
map.put("quantity", "20");
map.put("amount", "100");
map.put("price", "5");
data.add(map);
map = new HashMap<String,Object>();
map.put("code", "001");
map.put("name", "test");
map.put("quantity", "10");
map.put("amount", "200");
map.put("price", "20");
data.add(map);
map = new HashMap<String,Object>();
map.put("code", "002");
map.put("name", "test1");
map.put("quantity", "10");
map.put("amount", "200");
map.put("price", "20");
data.add(map);
map = new HashMap<String,Object>();
map.put("code", "003");
map.put("name", "test1");
map.put("quantity", "10");
map.put("amount", "200");
map.put("price", "20");
data.add(map);
List<Map<String,Object>> result = test.group(data,new String[]{"code","name"},
new String[]{"amount"},null,"");

DataUtils test1 = new DataUtils();
List<Map<String,Object>> result2 = test1.group(data, new String[]{"code","name"}, new String[]{"amount"}, null);

System.out.println(result2);

}

public String getKeyValueSplitChar() {
return keyValueSplitChar;
}

public void setKeyValueSplitChar(String keyValueSplitChar) {
this.keyValueSplitChar = keyValueSplitChar;
}

public String getFiledSplitChar() {
return filedSplitChar;
}

public void setFiledSplitChar(String filedSplitChar) {
this.filedSplitChar = filedSplitChar;
}
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值