`
ahua186186
  • 浏览: 561170 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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


分享到:
评论

相关推荐

    JAVA使用线程池查询大批量数据

    在Java开发中,处理大批量数据时,合理利用线程池可以显著提高程序的执行效率和资源利用率。本文将深入探讨如何在Java中使用线程池来查询大量数据,以及这样做的好处和实现方法。 首先,理解线程池的概念至关重要。...

    java解决大批量数据导出Excel产生内存溢出的方案

    在Java开发中,当面临大批量数据导出到Excel文件时,可能会遇到内存溢出的问题。这是因为Excel文件格式本身的设计,以及Java默认处理大数据的方式,可能导致内存占用过高,尤其是在一次性加载大量数据到内存中进行...

    非常完美Java实现年、月、日、周访问量统计

    在Java编程语言中,实现对年、月、日、周访问量的统计是一项常见的任务,尤其是在网站数据分析或者服务器日志处理中。这个任务涉及到日期时间处理、数据存储以及可能的数据聚合操作。以下是一些关键的知识点,可以...

    java实现csv导出千万级数据实例

    本实例聚焦于“java实现csv导出千万级数据实例”,旨在提供一个高效、稳定的解决方案,避免因数据量过大而导致的性能问题,如Java中的栈溢出(Stack Overflow)。CSV(Comma Separated Values)格式因其简单、通用性...

    java实现分组聚合

    在Java编程中,分组聚合是一项重要的数据处理技术,它允许我们按照特定的规则将数据组织成多个逻辑组,然后对这些组进行聚合操作,如计算每个组的总和、平均值等。这个主题通常与Java集合框架和流API紧密相关,特别...

    Java在Excel中创建多级分组、折叠或展开分组的实现

    Java在Excel中创建多级分组、折叠或展开分组的实现 Java在Excel中创建多级分组、折叠或展开分组的实现是指通过Java程序在Excel中创建多级分组、折叠或展开分组的方法。在Excel中,分组可以对行或列进行分组,并设置...

    mongoTemplate实现统计和分组

    "MongoDB 使用 MongoTemplate 实现统计和分组" MongoDB 是一个非常流行的 NoSQL 数据库,它可以存储大量的数据,但是有时候我们需要对这些数据进行分析和利用。在本文中,我们将介绍如何使用 MongoTemplate 实现...

    java多个数据库实现数据同步

    7. **微服务架构**:在微服务中,每个服务通常维护自己的数据库,通过API Gateway或Service Mesh进行服务间的通信,实现数据同步。这种方法强调服务自治,但需要良好的服务间协调机制。 在实现过程中,需要注意以下...

    java做大批量上传和下载

    在Java编程语言中,大批量上传和下载是常见的任务,特别是在处理大量数据或者文件交互的场景下。这个压缩包文件包含了一些关键的类,可以帮助我们理解如何在Java中实现这样的功能。下面将逐一解析这些类的功能及其在...

    java csv大数据量导出(千万级别,不会内存溢出)

    在Java开发中,处理大数据量的数据导出是一个常见的挑战,特别是在CSV格式的文件处理上。CSV(Comma Separated Values)是一种广泛使用的数据交换格式,因其简单性和通用性而受到青睐。然而,当数据量达到千万级别时...

    JAVA将一个数据中数据定时自动复制(抽取)到另一个数据库

    例如,我们可以定义一个继承自Thread的子类,重写`run`方法来实现数据抽取逻辑,或者使用`Runnable`接口配合`ExecutorService`来调度任务。 2. **定时任务**:Java提供了多种方式实现定时任务,如`java.util.Timer`...

    Java实现excel大数据量导入

    Java实现Excel大数据量导入是一项常见的任务,特别是在处理企业级数据导入导出时。Apache POI 是Java中广泛使用的库,用于处理Microsoft Office格式的文件,包括Excel。然而,当涉及大量数据时,直接使用POI的用户...

    java 按照每周分组

    在Java编程中,"按照每周分组"是一个常见的数据处理需求,特别是在数据分析、报表生成或者时间序列分析等场景。这个需求通常涉及到日期处理和集合分组。以下将详细讲解如何在Java中实现这一功能。 首先,我们需要...

    java实现Excel数据导入到数据库

    在Java中,实现Excel数据导入到数据库的步骤如下: 1. **读取Excel文件**:使用POI的`XSSFWorkbook`(针对.xlsx文件)或`HSSFWorkbook`(针对.xls文件)类打开Excel文件,然后通过`Sheet`和`Row`对象遍历并获取数据...

    java统计高并发首页访问量,记录客户登录信息

    在Java开发中,统计高并发环境下首页访问量并记录客户登录信息是一项常见的需求,这涉及到系统性能优化、数据持久化以及并发控制等多个方面。在这个项目中,开发框架选择了Spring,这是一个广泛使用的Java企业级应用...

    曲线拟合计算(java实现)

    通过Java实现的曲线拟合程序可以方便地集成到更大的软件系统中,进行定制化的数据分析。 总的来说,这个项目展示了如何利用Java进行曲线和直线拟合,涉及到的知识点包括:Java编程基础、数值分析中的最小二乘法、...

    Java实现Rtsp数据拆包组帧成H264帧

    本文将深入探讨如何使用Java实现RTSP数据的拆包组帧,并将其转换为H264数据帧。 首先,理解RTSP数据的传输过程至关重要。RTSP通过TCP或UDP传输RTP(实时传输协议)数据包,每个RTP包通常包含一个或多个连续的视频帧...

    几个推荐算法的java实现

    在压缩包中,`regeneration.py`可能是Python实现的相关代码,虽然主题是Java实现,但可能包含一些辅助脚本或测试数据。`readme.txt`通常包含项目的介绍、使用说明和作者信息,对于理解项目非常有帮助。而`dami`可能...

Global site tag (gtag.js) - Google Analytics