如果需要文件和代码的话可评论区留言邮箱,我给你发源代码

本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/hadoop-mapReduce-operator-case.html

实验要求

统计每个用户在不同时段中各个基站的停留时间。

1.功能描述

用户的手机,连接到不同的基站会产生一条记录。

数据格式为:用户标识 设备标识 基站位置 通讯的日期 通讯时间

example: 0000009999 0054785806 00000089 2016-02-21 21:55:37

需要得到的数据格式为:

用户标识 时段 基站位置 停留时间

example: 0000000001 09-18 00000003 15

用户0000000001在09-18点这个时间段在基站00000003停留了15分钟

2.实现思路

程序运行支持传入时间段,比如“09-18-24”,表示分为0点到9点,9点到18点,18点到24点三个时间段。

  • (1)Mapper阶段

    对输入的数据,算出它属于哪个时间段。

    k1:每行记录在文本中的偏移量。

    v2:一条记录

    k2用“用户ID,时间段”输出。

    v2用“基站位置,时间”。时间用unix time

  • (2)Reducer阶段

    对获取的v3(v3是一个集合,每个元素是v2,相当于按照k2对v2分组)进行排序,以时间升序排序。

    计算两两之间的时间间隔,保存到另一个集合中,两个不同的时间间隔中,从基站A移动到基站B,这样获取到在A基站的停留的时间。

    同理从基站B移动到基站C,基站C移动到基站D,依次类推,所有的时间都获取到。再把时间累加起来,就可以获取到总的时间。

本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/hadoop-mapReduce-operator-case.html

代码实现

PhoneMain.java

package phoneMapReduce;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException; /**
* Created by ue50 on 11/13/19.
*/
public class PhoneMain
{
public static void main(String[] args) throws InterruptedException, IOException, ClassNotFoundException
{
//String.equals()比较字符串的值是否相同
if(args == null || "0".equals(args[0]))
{
throw new RuntimeException("argument is not right!");
}
//Configuration是作业的配置信息类
Configuration configuration = new Configuration();
//set(String name, String value)设置配置项
configuration.set("timeRange", args[0]); Job job = Job.getInstance(configuration);
job.setJarByClass(PhoneMain.class); job.setMapperClass(PhoneMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputKeyClass(Text.class); job.setReducerClass(PhoneReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class); //FileInputFormat.setInputPaths(job, new Path("hdfs://xdata-m0:8020/user/ue50/pos.txt"));
//FileOutputFormat.setOutputPath(job, new Path("hdfs://xdata-m0:8020/user/ue50/out")); FileInputFormat.setInputPaths(job, new Path(args[1]));
FileOutputFormat.setOutputPath(job, new Path(args[2])); job.waitForCompletion(true);
}
}

Mapper阶段

PhoneMapper.java

package phoneMapReduce;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import java.io.IOException; /**
* Created by ue50 on 11/13/19.
*/
public class PhoneMapper extends Mapper<LongWritable, Text, Text, Text>
{
private int[] timeRangeList;
@Override
//setup()被MapReduce框架仅且执行一次,在执行Map任务前,进行相关变量或者资源的集中初始化工作
protected void setup(Context context) throws IOException,InterruptedException
{
//Configuration是作业的配置信息类,通过Configuration可以实现在多个mapper和多个reducer任务之间共享信息
Configuration configuration = context.getConfiguration(); //get(String name)根据配置项的键name获取相应的值
String timeRange = configuration.get("timeRange");//运行时传入的时间段,比如“09-18-24”
String[] timeRangeString = timeRange.split("-"); timeRangeList = new int[timeRangeString.length];
for(int i = 0; i < timeRangeString.length;i++)
{
//timeRangeList数组保存传入的时间,如:09、18、24
timeRangeList[i] = Integer.parseInt(timeRangeString[i]);
}
} @Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException
{
String values[] = value.toString().split("\\s+");//对一条记录"用户标识 设备标识 基站位置 通讯的时间"按空格拆分
String userId = values[0];//用户标识
String baseStation = values[2];//基站位置
String timeString = values[4];//访问时间,如:21:55:37 String[] times = timeString.split(":");//对访问时间按':'拆分
int hour = Integer.parseInt(times[0]);//小时 //startHour、endHour时间段的起止时间
int startHour = 0;
int endHour = 0;
for(int i = 0; i < timeRangeList.length; i++)
{
if(hour < timeRangeList[i])
{
if(i == 0)
{
startHour = 0;
}
else
{
startHour = timeRangeList[i-1];
}
endHour = timeRangeList[i];
break;
}
} if(startHour == 0 && endHour == 0)
{
return;
} //k2:用户标识 时间段 v2:基站位置-访问时间
context.write(new Text(userId + "\t" + startHour + "-" + endHour + "\t"), new Text(baseStation + "-" + timeString));
}
}

Reducer阶段

package phoneMapReduce;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*; /**
* Created by ue50 on 11/13/19.
*/
public class PhoneReducer extends Reducer<Text, Text, Text, LongWritable>
{
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException
{
List<String> valueList = new LinkedList<String>();//基于链表的动态数组 //Map是一种把键对象和值对象映射的集合,TreeMap是一个有序的key-value集合,
//它是通过红黑树实现的,TreeMap中的元素默认按照key的自然排序排列
Map<String, Long> residenceTimeMap = new TreeMap<String, Long>(); for(Text value : values)
{
String item = value.toString();
valueList.add(item);//"基站位置-访问时间"的集合
} if(valueList == null || valueList.size() <= 1)
{
return;
} //Comparator是比较器
//Collections.sort()方法中的自定义比较器,根据比较器的实现逻辑对valueList进行排序
Collections.sort(valueList, new Comparator<String>() {//匿名内部类
@Override
//重写比较器中的比较方法:compare方法
public int compare(String o1, String o2) {
o1 = o1.split("-")[1];
o2 = o2.split("-")[1];
return o1.compareTo(o2);//根据访问时间对valueList排序,第一个参数.compareTo(第二个参数)升序
}
}); for(int i = 0;i < valueList.size()-1; i++)
{
String station = valueList.get(i).split("-")[0];//基站位置
String time1 = valueList.get(i).split("-")[1];//访问时间
String time2 = valueList.get(i + 1).split("-")[1]; //对日期/时间进行格式化,HH:24小时制
DateFormat dateFormat = new SimpleDateFormat("HH:hh:ss");
//Date对象用于处理日期与时间
Date date1 = null;
Date date2 = null;
try{
date1 = dateFormat.parse(time1);//parse():把String型的字符串转换成特定格式的Date类型
date2 = dateFormat.parse(time2);
}catch (ParseException e)
{
e.printStackTrace();
} //date1.before(date2),当date1小于date2时,返回TRUE,当大于等于时,返回false;
if(date1.before(date2))
{
long time = date2.getTime() - date1.getTime();//getTime方法返回的是毫秒数 Long count = residenceTimeMap.get(station);//返回key关联的值,没有值返回null
if(count == null)
{
residenceTimeMap.put(station, time);//<基站位置,停留时间>
}
else
{
residenceTimeMap.put(station, count + time);//将停留时间累积
}
}
} valueList = null; //TreeMap的keySet():以升序返回一个具有TreeMap键的Set视图
Set<String> keySet = residenceTimeMap.keySet();//keySet:<基站位置>
for(String mapKey : keySet)
{
long minute = residenceTimeMap.get(mapKey);//停留时间毫秒
minute = minute/1000/60;//分钟
//minute = minute/1000;//秒 context.write(new Text(key +"\t" + mapKey +"\t"), new LongWritable(minute));
} residenceTimeMap = null;
}
}

如果需要文件和代码的话可评论区留言邮箱,我给你发源代码

hadoop MapReduce运营商案例关于用户基站停留数据统计的更多相关文章

  1. Hadoop MapReduce编程 API入门系列之挖掘气象数据版本2(十)

    下面,是版本1. Hadoop MapReduce编程 API入门系列之挖掘气象数据版本1(一) 这篇博文,包括了,实际生产开发非常重要的,单元测试和调试代码.这里不多赘述,直接送上代码. MRUni ...

  2. Hadoop MapReduce编程 API入门系列之挖掘气象数据版本3(九)

    不多说,直接上干货! 下面,是版本1. Hadoop MapReduce编程 API入门系列之挖掘气象数据版本1(一) 下面是版本2. Hadoop MapReduce编程 API入门系列之挖掘气象数 ...

  3. Hadoop MapReduce编程入门案例

    Hadoop入门例程简介 一个.有些指令 (1)Hadoop新与旧API差异 新API倾向于使用虚拟课堂(象类),而不是接口.由于这更easy扩展. 比如,能够无需改动类的实现而在虚类中加入一个方法( ...

  4. 大数据学习——mapreduce运营商日志增强

    需求 1.对原始json数据进行解析,变成普通文本数据 2.求出每个人评分最高的3部电影 3.求出被评分次数最多的3部电影 数据 https://pan.baidu.com/s/1gPsQXVYSQE ...

  5. 运营商如何关闭2G、3G网络?这事儿得从小灵通说起

    5G时代即将全面开启,主流声音是对未来的无限畅想--5G将带来翻天覆地的变化.不过凡事都有利弊两面性,5G作为新生事物固然大有可为,但不可避免地会对旧事物造成巨大冲击.除了会影响很多跟不上潮流发展的行 ...

  6. SIM卡的消失会让运营商们恐慌吗?

    ​中国移动.联通.电信三大运营商原本高高在上,每天乐滋滋地数钱数到手抽筋,但近年来移动互联网的快速普及,让运营商的制霸状态不复存在.成为众多互联网公司的"流量通道",语音.短信等业 ...

  7. 5G信令(就是用户身份信息)——手机开机后,先从USIM中读取之前运营商分配的临时身份信息GUTI/TMSI,发送携带该身份信息的信令给基站,请求接入运营商网络。

    5G时代,跟IMSI-CATCHER SAY GOODBYE from:https://unicorn.360.com/blog/2018/04/18/GoodBye_5G_IMSI-Catcher/ ...

  8. 【Hadoop】MapReduce自定义分区Partition输出各运营商的手机号码

    MapReduce和自定义Partition MobileDriver主类 package Partition; import org.apache.hadoop.io.NullWritable; i ...

  9. hadoop笔记之MapReduce的应用案例(利用MapReduce进行排序)

    MapReduce的应用案例(利用MapReduce进行排序) MapReduce的应用案例(利用MapReduce进行排序) 思路: Reduce之后直接进行结果合并 具体样例: 程序名:Sort. ...

随机推荐

  1. Linux内核链表之共享双链表

    说明 共享双链表意义在于,可以用一套函数维护不同数据类型的双链表 准备 定义双链表 #include <iostream> #include <string> using na ...

  2. 群晖下虚拟机编译部署WOW服务端TrinityCore

    前言 前几天突然想玩WOW了,但是我是一个特别轻度的玩家,以前点卡的时候,我就是上去一个人做做任务,跑跑地图,不怎么玩副本和PVP,现在让我花钱充月卡,不太现实,没那个时间玩,所以,就考虑玩个私服,但 ...

  3. js常用框架原理

    (function(){         //存储已经创建的模块     var moduleMap = {};     //判断是否已经加载过     var fileMap   = {};     ...

  4. 算法基础③--DFS解决迷宫问题入门

    迷宫问题 通过深度优先搜索(DFS)方法实现. 迷宫问题一 一天蒜头君掉进了一个迷宫里面,蒜头君想逃出去,可怜的蒜头君连迷宫是否有能逃出去的路都不知道. 看在蒜头君这么可怜的份上,就请聪明的你告诉蒜头 ...

  5. Jmeter监控平台搭建:JMeter+InfluxDB+Grafana

    背景 平时一般用Jmeter的Gui模式,添加对应的插件,查看每秒线程数.TPS.响应时间等曲线,其实高并发是不建议这么看的. 解决方案 可以搭配InfluxDB+Grafana工具,使Jmeter异 ...

  6. 清除安装的Rancher、K8s

    #清除主机的所有容器.挂载.镜像(慎用) docker stop $(docker ps -aq) docker system prune -f docker volume rm $(docker v ...

  7. 面试官:请用SQL模拟一个死锁

    文章首发于公众号:BiggerBoy 有读者说面试被问到怎么用SQL模拟数据库死锁? 这位读者表示对Java中的死锁还是略知一二的,但是突然用SQL写死锁的案例之前还真没遇到过,这个问题没答上来.所以 ...

  8. 1001-MySQL学习-第一节自习课

    MySQL学习(第一节自习课) 一. 软件下载.安装 下载地址:https://dev.mysql.com/downloads/installer/ 位置:mysql->installer-&g ...

  9. TCP 协议灵魂 12 问,巩固你的网路底层基础!

    点击上方"开源Linux",选择"设为星标" 回复"学习"获取独家整理的学习资料! 先亮出这篇文章的思维导图 TCP 作为传输层的协议,是一 ...

  10. 老生常谈系列之Aop--JDK动态代理的底层实现原理

    老生常谈系列之Aop--JDK动态代理的底层实现原理 前言 在Aop系列里面有两篇文章,分别是老生常谈系列之Aop--Spring Aop原理浅析和老生常谈系列之Aop--Spring Aop源码解析 ...