java数据透视表算法_用Java Steams创建数据透视表
【51CTO.com快译】这次让我们来看看如何使用Java 8 Streams(流)来实现一张数据透视表。通常情况下,原始数据本身一般并不容易被人们所读懂,因此我们需要进行一些数据聚合操作来辨别出原始数据中的各种规律模式。而数据透视表就是这样一种工具,它运用聚合的方法来展示出各种可视的图形和图表。
在过往的文章中,我们曾展示过如何使用Java 8 Streams进行类似SQL的效果对原始数据进行切割与分解。而今天的文章就建立在那些例子之上,如果你觉得这些对你有些难度的话,我建议你先通过如下链接浏览那两篇文章。
如果你不喜欢使用这种“原始数据”的方法来创建一张数据透视表,而选择使用Excel来实现的话,我为你提供了另外的备选方案,请参考如下链接:
将CSV数据表示为POJO
我们用如下的POJO(简单的Java对象,Plain Ordinary Java Object)来表示棒球运动员及其工资。
public class Player {
private int year;
private String teamID;
private String lgID;
private String playerID;
private int salary;
// defined getters and setters here
}
它的数据来自于一个简单的CSV文件,该文件内既没有引用的字段,也没有多行的字段,而且单个字段中还不存在着逗号。我们可以使用一个简单的正则表达式模式来解析该CSV文件,并将数据加载到一个列表之中。其数据看起来如下所示,它一共有大约26428行:
yearID,teamID,lgID,playerID,salary
198***TL,NL,barkele01,870000
198***TL,NL,bedrost01,550000
198***TL,NL,benedbr01,545000
198***TL,NL,campri01,633333
198***TL,NL,ceronri01,625000
...
我们用类似于如下代码的Streams加载CSV的数据:
Pattern pattern = Pattern.compile(",");
try (BufferedReader in = new BufferedReader(new FileReader(filename));){
List players = in
.lines()
.skip(1)
.map(line -> {
String[] arr = pattern.split(line);
return new Player(Integer.parseInt(arr[0]),
arr[1],
arr[2],
arr[3],
Integer.parseInt(arr[4]));
})
.collect(Collectors.toList());
}
定义数据透视表列的类
我们使用下面的类来定义数据透视表的各个列容器的类。这些列是用于对数据进行分组的。如果你使用的是SQL的话,这些列将出现在“GROUP BY”的语句中。
public class YearTeam
{
public int year;
public String teamID;
public YearTeam(int year,String teamID) {
this.year = year;
this.teamID = teamID;
}
@Override
public boolean equals(Object other)
{
if ( other == null ) return false;
if ( this == other ) return true;
if ( other instanceof YearTeam ) {
YearTeam yt = (YearTeam)other;
if ( year == yt.year && teamID.equals(yt.teamID) )
return true;
}
return false;
}
@Override
public int hashCode()
{
int hash = 1;
hash = hash * 17 + year;
hash = hash * 31 + teamID.hashCode();
return hash;
}
@Override
public String toString()
{
StringBuilder sbuf = new StringBuilder();
sbuf.append('[').append(year).append(", ").append(teamID)
.append(']');
return sbuf.toString();
}
}
仅仅是为了方便起见,这些字段被定义为了“public(公有)”访问属性。而对于你自己的应用程序,你完全可以将其设置为“private(私有)”属性,并根据需要添加getter和/或setter。
这个类覆盖重写了equals()和hashCode(),因为它将在存储一张Map(映射表)时被作为key(键)使用。
用Streams分组数据
我们在此读取该CSV的数据,为每一行创建一个POJO,并用上面所定义的透视表列的类来对数据进行分组。
Map> grouped = in
.lines()
.skip(1)
.map(line -> {
String[] arr = pattern.split(line);
return new Player(Integer.parseInt(arr[0]),
arr[1],
arr[2],
arr[3],
Integer.parseInt(arr[4]));
})
.collect(Collectors.groupingBy(x-> new YearTeam(x.getYear(), x.getTeamID())));
至此,这些数据已被正确地收集到了在一张Map(映射表)中,并按指定的列项进行了分组。
将数据透视表打印成CSV
让我们将数据透视表里的数据打印成一个CSV文件,以便我们可以将其加载到Excel中用以比较。在打印数据的时候,我们用到了求和函数summingLong()。Java 8 Streams同样也提供了averagingLong()函数让你求出平均值。如果你需要一次性地快速获取的话,那么summarizingLong()就能够将所有信息呈现到你的面前,请尽情享用吧!
CSV列的头部标题
我们使用teamID的各个数值来作为列的头部标题。对它们的收集和打印操作,如下所示。我们这里使用TreeSet来对其进行字母顺序的排列。
Set teams = grouped
.keySet()
.stream()
.map(x -> x.teamID)
.collect(Collectors.toCollection(TreeSet::new));
System.out.print(',');
teams.stream().forEach(t -> System.out.print(t + ","));
System.out.println();
打印数据
这样就创建并打印出来一张完整的数据透视表。对于团队每年的总和,我们从运动员列表中提取出来,并执行一个加总和打印的操作。
Set years = grouped
.keySet()
.stream()
.map(x -> x.year)
.collect(Collectors.toSet());
years
.stream()
.forEach(y -> {
System.out.print(y + ",");
teams.stream().forEach(t -> {
YearTeam yt = new YearTeam(y, t);
List players = grouped.get(yt);
if ( players != null ) {
long total = players
.stream()
.collect(Collectors.summingLong(Player::getSalary));
System.out.print(total);
}
System.out.print(',');
});
System.out.println();
});
比较来自Excel的输出
我们将该CSV文件加载到Excel中并输出如下数据:
用Excel自带的数据透视表功能进行比较,可见这些数据是相同的。(如下所示,由于某种原因,列“MON”出现在了Excel的前端。也许这是诸多神奇“特性”中的一种吧。反正各个数值都是相同的。)
朋友们,这就是使用Java自带的简单Collections(类集)来创建数据透视表的一种方法。你可以通过它去发现更多酷炫的用途!
总结
数据透视表的确是一种十分有用的数据汇总工具。大多数的数据分析软件,包括Excel都有用到它。在此,我们学会了如何使用Java 8 Streams来创建出相同的数据结构。同时,我们也用到了分组和加总来实现该功能。
【原标题】Making Pivot Table Using Java Streams (作者: Jay Sridhar )
【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】
【责任编辑:刘晓旭 TEL:(010)68476606】
点赞 0
java数据透视表算法_用Java Steams创建数据透视表相关推荐
- java矩阵连乘算法_使用java写的矩阵乘法实例(Strassen算法)
Strassen算法于1969年由德国数学家Strassen提出,该方法引入七个中间变量,每个中间变量都只需要进行一次乘法运算.而朴素算法却需要进行8次乘法运算. 原理 Strassen算法的原理如下 ...
- java编写字母z算法_【Java】【每日算法/刷穿 LeetCode】6. Z 字形变换(中等)
首页 专栏 java 文章详情 0 [每日算法/刷穿 LeetCode]6. Z 字形变换(中等) 宫水三叶发布于 今天 12:03 题目描述 将一个给定字符串 s 根据给定的行数 numRows , ...
- java阶乘和的算法_关于JAVA阶乘的算法的解释?
第一个for循环是求和 第二个是求阶乘 这样看更易理解 class jie { private static int ji(int i){ int ji=1; for(int j =1;j<=i ...
- 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目
王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...
- java jvm垃圾回收算法_深入理解JVM虚拟机2:JVM垃圾回收基本原理和算法
本文转自互联网,侵删 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 喜欢的话麻烦点下Star哈 文章将同步到我的个人博客: www.how ...
- java 哈希一致算法_一致哈希算法Java实现
一致哈希算法(Consistent Hashing Algorithms)是一个分布式系统中常用的算法.传统的Hash算法当槽位(Slot)增减时,面临所有数据重新部署的问题,而一致哈希算法确可以保证 ...
- java 离散算法_用JAVA语言实现离散数学算法
用JAVA语言实现离散数学算法 用JAVA语言实现离散数学算法 * 显示离散数学算法的真值表 * 提供将一个中缀合适公式的真值表输出到某一PrintStream流中的功能 * 以单个大写字母表示变量( ...
- 6种java垃圾回收算法_学习java垃圾回收
垃圾回收(GC)一直是Java受欢迎背后的重要特性之一.垃圾回收是Java中用于释放未使用的内存的机制.本质上,它追踪所有仍在使用的对象,并将剩下的标记为垃圾.Java的垃圾回收被认为是一种自动内存管 ...
- JAVA两个表相关联_关于Java:如何将多对多关联映射到映射到两个不同表的类?...
我有一个凭证-POJO映射到两个表. 第一个映射分配一个实体名称" voucherA",并将POJO映射到TableA. 第二个映射使用" voucherB"作 ...
- java list 前100个_实现java 中 list集合中有几十万条数据,每100条为一组取出
解决"java 中 list集合中有几十万条数据,每100条为一组取出来如何实现,求代码!!!"的问题. 具体解决方案如下: /** * 实现java 中 list集合中有几十万条 ...
最新文章
- Scott Mitchell 的ASP.NET 2.0数据教程之一: 创建一个数据访问层
- 鸿蒙申请敏感应用怎么选择,申请鸿蒙系统有一个应用选择怎么选择呢
- x265-创建encdata
- PHP - 会话控制
- 北大清华团队编写!200多个科学实验+视频,和爸爸一起在家做
- 删除一个无头单链表的非尾节点(C语言)
- 做到这几点,让你离高级程序员更近一步!
- CIO必看:7个常见但一定要避免的数据治理错误
- 2017年9月全国计算机等级考试报名时间,关于2017年9月全国计算机等级考试网上报名工作的通知...
- html中div的居中
- useradd/adduser 添加用户
- delphi xe android 黑屏,Delphi XE之路(3)解决启动时短暂的黑屏
- umount target is busy
- 程序员辉辉想裸辞,但又不太敢
- android studio 如何上传文件到模拟器的根目录
- CString、CStringA 和 CStringW
- CAS4.0配置Mysql数据库,认证失败
- 欧拉定理,费马小定理证明
- 四、SpringMVC文件上传
- idm一个网站不能下载两次?这几个办法彻底解决