`
ahua186186
  • 浏览: 563050 次
  • 性别: 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解决大批量数据导出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中使用poi导出Excel大批量数据到客户端

    在java web系统应用中我们经常会用到大批量数据的导出,动辄就上几十万几百万的数据让我们的程序感觉压力很大,甚至都出现无法导出的情况,如内存溢出等。 java中使用poi导出Excel大批量数据到客户端 存在两个导出...

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

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

    java导出大批量(百万以上)数据的excel文件

    在Java开发中,导出大量数据到Excel文件是一项常见的任务,尤其在数据分析、报表生成或者数据备份等场景中。然而,处理百万级别的数据时,传统的直接将所有数据一次性写入Excel文件的方式可能会导致内存消耗过大,...

    java做大批量上传和下载

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

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

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

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

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

    用java实现word统计报表和图形统计的导出

    在给定的标题“用java实现word统计报表和图形统计的导出”中,我们可以理解到这个项目或教程旨在教我们如何使用Java来创建包含统计报表和图形的Microsoft Word文档。这通常涉及到两个关键领域:文本处理和数据可视化...

    Java实现excel大数据量导入

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

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

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

    Xmodem和Ymodem 传输协议JAVA实现

    本文将深入探讨这两种协议的工作原理,并提供它们在Java环境中的实现。 **Xmodem协议** Xmodem是最简单的文件传输协议之一,每一步传输128字节的数据块。它通过校验和机制来检测数据传输中的错误。Xmodem协议分为两...

    kmeans聚类java实现附测试数据及结果

    KMeans聚类是一种广泛应用的无监督机器学习算法,主要用于数据的分类和分组。在Java中实现KMeans聚类,可以使用多种库,如Weka、Apache Mahout或自行编写代码。下面我们将深入探讨KMeans聚类的基本原理、Java实现的...

    曲线拟合计算(java实现)

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

    几个推荐算法的java实现

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

Global site tag (gtag.js) - Google Analytics