Java实现文本文件分组汇总的简便方法

程序开发中经常会碰到处理文本文件中数据的情况,这里通过一个例子来看用java实现文本文件分组汇总的方法:从文本文件employee.txt中读取员工信息,按照DEPT分组,求出每组的员工个数COUNT和薪酬SALARY总额。

文本文件empolyee.txt的格式如下:

EID   NAME       SURNAME        GENDER  STATE        BIRTHDAY        HIREDATE         DEPT         SALARY

1       Rebecca   Moore      F       California 1974-11-20       2005-03-11       R&D          7000

2       Ashley      Wilson      F       New York 1980-07-19       2008-03-16       Finance    11000

3       Rachel      Johnson   F       New Mexico     1970-12-17       2010-12-01       Sales         9000

4       Emily         Smith        F       Texas        1985-03-07       2006-08-15       HR    7000

5       Ashley      Smith        F       Texas        1975-05-13       2004-07-30       R&D          16000

6       Matthew Johnson   M     California 1984-07-07       2005-07-07       Sales         11000

7       Alexis        Smith        F       Illinois       1972-08-16       2002-08-16       Sales         9000

8       Megan     Wilson      F       California 1979-04-19       1984-04-19       Marketing        11000

9       Victoria    Davis        F       Texas        1983-12-07       2009-12-07       HR    3000

10     Ryan         Johnson   M     Pennsylvania    1976-03-12       2006-03-12       R&D          13000

11     Jacob        Moore      M     Texas        1974-12-16       2004-12-16       Sales         12000

12     Jessica     Davis        F       New York 1980-09-11       2008-09-11       Sales         7000

13     Daniel       Davis        M     Florida      1982-05-14       2010-05-14       Finance    10000

Java程序的编写思路是:

1、  从文件逐行读入数据保存到List对象sourceList的多个Map对象emp中。

2、  遍历sourceList对象,按照DEPT分组保存到Map对象group的不同List对象list中。

3、  再遍历group,针对每一个DEPT,遍历其list对象,累加SALARY。

4、  遍历group的同时,将DEPT,COUNT,SALARY的值存入Map对象result。不同部门的result存入List对象resultList中。

5、  打印出resultList的数据。

具体代码如下:

public static void myGroup() throws Exception{

File file = newFile("D:\\esProc\\employee.txt");

FileInputStream fis = null;

fis = new FileInputStream(file);

InputStreamReader input = newInputStreamReader(fis);

BufferedReader br = newBufferedReader(input);

String line = null;

String info[] = null;

List<Map<String,String>>sourceList= new ArrayList<Map<String,String>>();

List<Map<String,Object>> resultList=new ArrayList<Map<String,Object>>();

if ((line = br.readLine())== null)return;//第一行舍弃

while((line = br.readLine())!= null){

info =line.split("\t");

Map<String,String>emp=new HashMap<String,String>();

emp.put("EID",info[0]);

emp.put("NAME",info[1]);

emp.put("SURNAME",info[2]);

emp.put("GENDER",info[3]);

emp.put("STATE",info[4]);

emp.put("BIRTHDAY",info[5]);

emp.put("HIREDATE",info[6]);

emp.put("DEPT",info[7]);

emp.put("SALARY",info[8]);

sourceList.add(emp);

}

Map<String,List<Map<String,String>>>group = new HashMap<String,List<Map<String,String>>>();

//分组对象

for (int i = 0, len =sourceList.size(); i < len; i++) {//将明细数据分组

Map<String,String> emp=(Map) sourceList.get(i);

if(group.containsKey(emp.get("DEPT"))){

group.get(emp.get("DEPT")).add(emp) ;

} else {

List<Map<String,String>> list = newArrayList<Map<String,String>>() ;

list.add(emp) ;

group.put(emp.get("DEPT"),list) ;

}

}

Set<String> key =group.keySet();

for (Iterator it = key.iterator();it.hasNext();) {//将分组数据汇总

String dept = (String)it.next();

List<Map<String,String>>list = group.get(dept);

double salary =0;

for (int i = 0, len =list.size(); i < len; i++) {

salary +=Float.parseFloat(list.get(i).get("SALARY"));

}

Map<String,Object>result=new HashMap<String,Object>();

result.put("DEPT",dept);

result.put("SALARY",salary);

result.put("COUNT",list.size());

resultList.add(result);

}

for (int i = 0, len =resultList.size(); i < len; i++) {//打印结果数据

System.out.println("dept="+resultList.get(i).get("DEPT")+

"||salary="+resultList.get(i).get("SALARY")+

"||count="+resultList.get(i).get("COUNT"));

}

}

执行结果如下:

dept=Sales||salary=1362500.0||count=187

dept=Finance||salary=177500.0||count=24

dept=Administration||salary=40000.0||count=4

dept=Production||salary=663000.0||count=91

dept=Marketing||salary=733500.0||count=99

这个myGroup函数的分组字段只有一个,如果有多个的话,需要嵌套多重的集合类,代码就会更复杂了。而且myGroup函数的分组字段和汇总字段都是固定的,如果字段发生了变化,只能修改程序,无法处理灵活的动态分组汇总。如果希望myGroup像SQL语句那样适用于动态分组汇总,就需要编写动态表达式解析和求值的程序,编写难度相当大。

采用集算器esProc辅助是个更轻松的方案。集算器是专门为结构化(半结构化)数据处理设计的开发语言,实现灵活分组汇总任务很轻松,并和Java程序能无缝结合,从而使Java程序可以象SQL那样灵活访问和处理文本文件中的数据。

例如,我们需要按照DEPT分组,求出每组的员工个数COUNT和薪酬SALARY总额,esProc程序可以从外部传入一个输入参数“groupBy”作为动态的分组和汇总条件,如下图:

“groupBy”的值是:DEPT:dept;count(~):count,sum(SALARY):salary。具体的esProc代码只需要三行,如下:

A1:定义一个file对象,导入数据,第一行是标题,字段分隔符默认是tab。esProc的集成开发环境可以直观的显示出导入的数据,如上图右边部分。

A2:按照指定字段分组汇总。这里使用宏来实现动态解析表达式,其中的groupBy就是传入参数。集算器将先计算${…}里的表达式,将计算结果作为宏字符串值替换${…}之后解释执行。这个例子中最终执行的是:=A1.groups(DEPT:dept;count(~):count,sum(SALARY):salary)。

A3:向外部程序返回符合条件的结果集。

分组字段发生变化时不用改变程序,只需改变groupBy参数即可。例如,分组变为:按照DEPT和GENDER两个字段分组,求出每组的员工个数COUNT和薪酬SALARY总额。groupBy的参数值可以写为:DEPT:dept,GENDER:gender;count(~):count,sum(SALARY):salary。执行之后,A2中的结果集如下图:

最后,还需要在Java程序中调用这段esProc程序获得分组汇总结果,使用esProc提供的jdbc即可完成。将上述esProc程序保存为test.dfx文件的话,Java调用的代码如下:

//建立esProc jdbc连接

Class.forName("com.esproc.jdbc.InternalDriver");

con= DriverManager.getConnection("jdbc:esproc:local://");

//调用esProc 程序(存储过程),其中test是dfx的文件名

com.esproc.jdbc.InternalCStatementst;

st =(com.esproc.jdbc.InternalCStatement)con.prepareCall("calltest(?)");

//设置参数

st.setObject(1,"DEPT:dept,GENDER:gender;count(~):count,sum(SALARY):salary");//参数就是动态的分组汇总字段

//执行esProc存储过程

st.execute();

//获取结果集

ResultSet set = st.getResultSet();

这里的集算器代码比较简单,可以在Java程序中直接调用,不必再写集算器的脚本文件(比如上边的test.dfx)。具体代码如下:

st=(com.esproc.jdbc.InternalCStatement)con.createStatement();

ResultSetset=st.executeQuery("=file(\"D:\\\\esProc\\\\employee.txt\")[email protected]().groups(DEPT:dept,GENDER:gender;count(~):count,sum(SALARY):salary)");

上面的Java代码直接调用了一句集算器语句:从文本文件中读取数据,按照指定字段分组和汇总之后,将结果返回给Java程序的ResultSet对象set。

时间: 2025-01-02 03:42:33

Java实现文本文件分组汇总的简便方法的相关文章

Java实现文本文件按条件过滤的简便方法

程序开发中经常会碰到处理文本文件中数据的情况,这里通过一个例子来看用java实现文本文件按条件过滤的方法:从文本文件employee.txt中读取员工信息,从中找出1981年1月1日(含)之后出生的女员工. 文本文件empolyee.txt的格式如下: EID   NAME       SURNAME        GENDER  STATE        BIRTHDAY        HIREDATE         DEPT         SALARY 1       Rebecca  

R实现大文本文件数据分组汇总的方法

使用R语言对文件数据分组汇总是很普遍的操作,但有时我们会遇到比较大的文件,这类文件的计算结果较小,但源数据太大,无法全部放入内存进行计算,只能采用分批读取.分批计算.拼合结果的办法来解决.下面用一个例子来说明R实现大文件数据分组汇总的方法. 有个1G的文件sales.txt,存储着大量订单记录,我们要对CLIENT字段分组并对AMOUNT字段汇总.该文件的列分割符为"\t",前几行数据如下: R语言解决方案     con <- file("E: \\sales.txt

集算器协助Java处理结构化文本之分组汇总

直接用Java实现文体文件分组汇总会有如下的麻烦: 1.文件不是数据库,不能用SQL访问.当分组.汇总表达式变化时,只能改写代码.而要实现灵活表达式的话,需要自己实现动态表达式解析和求值,编程工作量非常大. 2.遍历过程中记录分组结果,结果小了还可以存在内存中,如果分组结果太大时要将中间结果缓存进临时文件再归并,实现过程非常复杂. 使用集算器辅助Java编程,这些问题都有现成的类库可以解决.下面,我们通过例子来看一下具体作法. 文本文件employee.txt中保存有员工信息,我们要按照DEPT

R语言实现固定分组汇总的方法

组名称和组数量已知的分组汇总被称为固定分组汇总,此类算法的分组依据来自于数据集之外,比如:按照参数列表中的客户名单分组,或按照条件列表进行分组.此类算法会涉及分组依据是否超出数据集.是否需要多余的组.数据是否重叠等问题,解决起来有一定的难度.本文将介绍R语言实现固定分组汇总的方法.  例1:分组依据不超出数据集 数据框sales是订单记录,其中CLIENT列是客户名,AMOUNT列是订单金额,请将sales按照"潜力客户列表"进行分组,并对各组的AMOUNT列汇总求和.潜力客户列表为[

SQL对取值范围进行分组汇总的几种办法

在统计工作中,我们经常遇到对一个数量的取值范围进行分组汇总的情况,比如假定id取值为1~20000,按照组距5000进行分组,我们要分别求出5000以下包括5000,5000以上10000以下包括10000,10000以上15000以下包括15000,15000以上20000以下包括20000.的计数,可以用内置取整函数ceil和除法运算得到.select ceil(id/5000) f, count(1) cnt from t1 group by ceil(id/5000) order by

最新Java开发面试题汇总

原文地址:www.jianshu.com/p/faaa4c2a4-前言为了方便之后的面试复习,我把各类面试题给汇总了一下,每道题都是经过自己筛选后觉得需要掌握的,此次整理包括 Java.数据结构与算法.计算机网络.操作系统.数据库等.文末我会把这些完整的答案放送给大家.Java 篇(1). Java基础知识java中==和equals和hashCode的区别int与integer的区别抽象类的意义接口和抽象类的区别能否创建一个包含可变对象的不可变对象?谈谈对java多态的理解String.Str

细节决定成败--记初学Power Query之分组汇总问题解决

在今天用手头资料联系PQ时,出现含税金额项完全是数字格式的,分组汇总求和提示有错误值,错误提示:DataFormat.Error.无法转换为Number.详细信息q.各种百度居然搜不到类似PQ的解决方法.碰巧加入曾老师的"Excel Power Query交流群"受到启发,居然是添加条件列之前的那一列的格式没统一导致汇总依据列的连贯错误.还好最后测试解决.强烈建议以后的各位PQ处理数据前先确认各列数据的属性,再进行相关的运算汇总. 原文地址:https://blog.51cto.com

Java报错原因汇总

1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序 遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的对象,这个错误经常出现在创建图片,调用数组这些操作中,比如图片 未经初始化,或者图片创建时的路径错误等等.对数组操作中出现空指针,很多情况下是一些刚开始学习编程的朋友常犯的错误,即把数组的初始化和数组元素的初 始化混淆起来了.数组的初始化是对数组分配需要的空间,而初始化后的数组,其中的元素并没有实例化,依然是

Java 计算中英文长度的若干种方法

在项目开发中经常碰到到输入字符的校验,特别是中英文混合在一起的校验.而为了满足校验的需求,有时需要计算出中英文的长度. 本文将通过几种常用的方法实现长度的计算: <span style="font-size:18px;">import java.io.UnsupportedEncodingException; /** * 中英文校验的处理 * @author a123demi * */ public class EnChValidate { public static vo