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;
	}
}


猜你喜欢

转载自ahua186186.iteye.com/blog/2264972
今日推荐