MapReduce实现手机上网日志分析(排序)
一、背景
1.1 流程
实现排序,分组拍上一篇通过Partitioner实现了。
实现接口,自动产生接口方法,写属性,产生getter和setter,序列化和反序列化属性,写比较方法,重写toString,为了方便复制写够着方法,不过重写够着方法map里需要不停地new,发现LongWritable有set方法,text也有,可以用,产生默认够着方法。
public void set(String account,double income,double expense,double surplus) {
this.account = account;
this.income = income;
this.expense = expense;
this.surplus = income-expense;
}
1.2 数据集
为了和上一篇保在知识上持递进,数据及换了,名字没变。
下面是输出结果,其实mr也会自动排序,不过string按字典序排序了。
二、理论知识
字符串拼接,记得以前自己写过,现在拿出来看看,http://www.cnblogs.com/hxsyl/archive/2012/10/18/2729112.html
简单总结扩展如下:String是final的,不能改变也不能继承,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响,特别当内存中无引用对象多了以后, JVM 的 GC 就会开始工作,那速度是一定会相当慢的。
如果for循环1w次,这句 string += "hello";的过程相当于将原有的string变量指向的对象内容取出与"hello"作字符串相加操作再存进另一个新的String对象当中,再让string变量指向新生成的对象。反编译出的字节码文件可以很清楚地看出,每次循环会new出一个StringBuilder对象,然后进行append操作,最后通过toString方法返回String对象。也就是说这个循环执行完毕new出了10000个对象,试想一下,如果这些对象没有被回收,内存浪费不说,有可能重复使用赵成系统卡死。从上面还可以看出:string+="hello"的操作事实上会自动被JVM优化成:
StringBuilder str = new StringBuilder(string);
str.append("hello");
str.toString();
如果直接for循环里StringBuilder 的话会只是new一次。效率高。
而StringBuffer是线程安全的,多了synchronized关键字,也就是在多线程下会顺序读取换冲刺。
参考了这个http://blog.csdn.net/loveyaozu/article/details/47037957
三、实体类
收入相同的话按消费从低到高,否则收入从高到低。
package cn.app.hadoop.mr.sort; import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.math.BigDecimal; import org.apache.hadoop.io.WritableComparable;
import org.apache.jasper.tagplugins.jstl.core.Out; //Writable是序列化接口
//泛型是InfoBean,就像比较学生信息一样,成绩,性别等 ,封装在了一个bean里
//不过发现WritableComparable 有了序列化和反序列化
public class InfoBean implements WritableComparable<InfoBean>{ private String account;
//金钱类都需要BigDecimal,double顺势精度,不过不知道下边序列化咋写类型,所以先用double,估计writeUTF可以
private double income;
private double expense;
private double surplus; public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public double getIncome() {
return income;
}
public void setIncome(double income) {
this.income = income;
}
public double getExpense() {
return expense;
}
public void setExpense(double expense) {
this.expense = expense;
}
public double getSurplus() {
return surplus;
}
public void setSurplus(double surplus) {
this.surplus = surplus;
}
public void readFields(DataInput in) throws IOException {
// TODO Auto-generated method stub
this.account = in.readUTF();
this.income = in.readDouble();
this.expense = in.readDouble();
this.surplus = in.readDouble();
}
public void write(DataOutput out) throws IOException {
// TODO Auto-generated method stub
out.writeUTF(account);
out.writeDouble(income);
out.writeDouble(expense);
out.writeDouble(surplus); } public void set(String account,double income,double expense) {
this.account = account;
this.income = income;
this.expense = expense;
this.surplus = income - expense;
} public InfoBean() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "InfoBean [income=" + income + ", expense=" + expense
+ ", surplus=" + surplus + "]";
}
public int compareTo(InfoBean o) {
// TODO Auto-generated method stub
if(this.income == o.getIncome()) {
return this.expense>o.getExpense()?1:-1;
}else {
return this.income>o.getIncome()?-1:1;
}
}
}
四、第一种实现
4.1 Mapper
//第一个处理文本的话一般是LongWritable 或者object
//一行一行的文本是text
//输出的key的手机号 定位Text
//结果是DataBean 一定要实现Writable接口
public class InfoSortMapper extends Mapper<LongWritable, Text, Text, InfoBean> { private InfoBean v = new InfoBean();
private Text k = new Text(); public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] fields = line.split("\t");
String account = fields[0];
double in = Double.parseDouble(fields[1]);
double out = Double.parseDouble(fields[2]); //不用每次new 几遍不重写内存引用,也很站用资源
k.set(account);
v.set(account, in, out); context.write(k, v);
}
4.2 Reducer
public class InfoSortReducer extends Reducer<Text, InfoBean, Text, InfoBean> { //k就是key,不需要
private InfoBean v = new InfoBean();
public void reduce(Text key, Iterable<InfoBean> value, Context context)
throws IOException, InterruptedException {
// process values
double incomeSum = 0;
double expenseSum = 0;
for (InfoBean o : value) {
incomeSum += o.getIncome();
expenseSum += o.getExpense();
}
v.set(key.toString(), incomeSum, expenseSum);
//databean会自动调用toString
context.write(key,v);
}
}
五、第二种实现
5.1 Mapper
//对 InfoBean 排序 k2就是他
public class SortMapper extends Mapper<LongWritable, Text, InfoBean, NullWritable> { private InfoBean k = new InfoBean();
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] fields = line.split("\t");
String account = fields[0];
double in = Double.parseDouble(fields[1]);
double out = Double.parseDouble(fields[2]); //不用每次new 几遍不重写内存引用,也很站用资源
k.set(account, in, out);
//value必须是NullWritable.get(),NullWritable不行,提示不是变量
context.write(k, NullWritable.get());
}
}
5.2 Reducer
//对 InfoBean 排序 k2就是他
public class SortMapper extends Mapper<LongWritable, Text, InfoBean, NullWritable> { private InfoBean k = new InfoBean();
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] fields = line.split("\t");
String account = fields[0];
double in = Double.parseDouble(fields[1]);
double out = Double.parseDouble(fields[2]); //不用每次new 几遍不重写内存引用,也很站用资源
k.set(account, in, out);
//value必须是NullWritable.get(),NullWritable不行,提示不是变量
context.write(k, NullWritable.get());
}
}
六、结束语
如果k2 v2和k4 v4,也就是mapp的输出和reducer的输出类型不一致的话必须在Main里也设置Mapper的输出,上面的第二种就是。
job.setMapOutputKeyClass(InfoBean.class);
job.setMapOutputValueClass(NullWritable.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(InfoBean.class);
否则java里不报错,加上log4j后看到类型不匹配。
MapReduce实现手机上网日志分析(排序)的更多相关文章
- MapReduce实现手机上网日志分析(分区)
一.问题背景 实际业务的需要,比如以移动为例,河南的用户去了北京上网,那么他的上网信息默认保存在了北京的基站,那么我们想要查询北京地区的上网日志信息默认也包含了其他地区用户的在本区的上网信息,否则只能 ...
- MapReduce实现手机上网流量分析(业务逻辑)
一.问题背景 现在的移动刚一通话就可以在网站上看自己的通话记录,以前是本月只能看上一个月.不过流量仍然是只能看上一月的. 目的就是找到用户在一段时间内的上网流量. 本文并没有对时间分组.下一节进行分区 ...
- 使用Pig对手机上网日志进行分析
在安装成功Pig的基础上.本文将使用Pig对手机上网日志进行分析,详细过程例如以下: 写在前面: 手机上网日志文件phone_log.txt.文件内容 及 字段说明部分截图例如以下 需求分析 显示每一 ...
- Hadoop自定义类型处理手机上网日志
job提交源码分析 在eclipse中的写的代码如何提交作业到JobTracker中的哪?(1)在eclipse中调用的job.waitForCompletion(true)实际上执行如下方法 con ...
- Hadoop学习笔记—5.自定义类型处理手机上网日志
转载自http://www.cnblogs.com/edisonchou/p/4288737.html Hadoop学习笔记—5.自定义类型处理手机上网日志 一.测试数据:手机上网日志 1.1 关于这 ...
- Hadoop日记Day13---使用hadoop自定义类型处理手机上网日志
测试数据的下载地址为:http://pan.baidu.com/s/1gdgSn6r 一.文件分析 首先可以用文本编辑器打开一个HTTP_20130313143750.dat的二进制文件,这个文件的内 ...
- Hadoop学习笔记—20.网站日志分析项目案例(一)项目介绍
网站日志分析项目案例(一)项目介绍:当前页面 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edisonchou/p/4458219.html 网站日志分析项目案例 ...
- ELK日志分析平台环境部署 (yum安装)
前言:通常体质被分散存储在不同的设备上面,在庞大的服务器集群中,我们需要集中化的管理,日志的统计和检索,一般我们使用grep和awk,wc等linux命令虽然能够实现检索和统计,但是呢,对于要求更高的 ...
- Hadoop学习笔记—20.网站日志分析项目案例
1.1 项目来源 本次要实践的数据日志来源于国内某技术学习论坛,该论坛由某培训机构主办,汇聚了众多技术学习者,每天都有人发帖.回帖,如图1所示. 图1 项目来源网站-技术学习论坛 本次实践的目的就在于 ...
随机推荐
- iOS开发之聊天模块--内容保存逻辑实现
需求详解: 在实际开发中,有可能是在后期优化的时候,会有这么需要优化的需求:聊天输入框保存之前输入的文本,提高用户的良好体验. 在聊天模块中,用户可能会在输入框输入若干字符,但是没有点击发送就点击退出 ...
- StringBuilder用法
//来自MSDN,不太懂英文可以使用百度翻译. //using System; //using System.Text; //public sealed class App //{ // static ...
- SQL SERVER出现大量一致性错误的解决方法
如果DBCC CHECKDB发现了比较少的一致性错误,可以使用 DBCC UPDATEUSAGE(DatabaseName,"dbo.ObjectName"); 语句逐个针对表 ...
- SQL Server里面如何检查没有释放的游标
一直以来对SQL SERVER的游标都不怎么感冒,也很少使用SQL Server里面的游标,前几天有一位网友问如何检查数据库里面没有释放的游标,觉得有点意思,就测试验证了一下,顺便整理于此. 会话1: ...
- Cannot create an instance of OLE DB provider "OraOLEDB.Oracle" for linked server "xxxxxxx".
在SQL SERVER 2008 R2下用Windows 身份认证的登录名创建了一个访问ORACLE数据库的链接服务器xxxxx,测试成功,木有问题,但是其它登录名使用该链接服务器时,报如下错误: 消 ...
- HTML基本组成结构与标签的认识
HTML基本组成结构与标签 其实组成结构用一张图来简单了解下如下 目前一般网站的结构是会如此不是很清晰简单 先来说说header头部 这样是不是更加清楚了 导航栏是引导用户查看网站内容的快捷入口,打个 ...
- 【java开发】数组基本学习
一维数组 定义:具有相同数据类型的一组数据. 声明:int []a=new int[3]; 释义:该数组的数据类型为int型,该数组长度为3,有3个元素 可采用如下方式为元素赋值:a[0]=1; ...
- hadoop.home.dir is not set
今天遇到一个错误,JAVA堆栈如下: 是在获取文件系统对象的时候出错,没有找到环境变量 HADOOP_HOME or hadoop.home.dir ,但是在本地一直没有重现这个问题. 这个问题是一个 ...
- 理解CSS相对定位和固定定位
× 目录 [1]相对定位 [2]固定定位 前面的话 一般地,说起定位元素是指position不为static的元素,包括relative.absolute和fixed.前面已经详细介绍过absolut ...
- MMORPG大型游戏设计与开发(服务器 游戏场景 聊天管道和寻路器)
又快到双十一,又是不少同仁们出血的日子,首先希望大家玩的开心.我曾经想要仔细的剖析场景的的每个组件,就像这里的聊天管道与寻路器,但是仔细阅读别人代码的时候才发现元件虽小但是实现并不简单,因为有些东西还 ...