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

本文来自博客园,作者: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. jsp中c:forEach使用

    首先需要在jsp中引入<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> ...

  2. MPU9250/MPU6050与运动数据处理与卡尔曼滤波(1)

    第一篇--概述和MPU6050及其自带的DMP输出四元数 概述 InvenSense(国内一般译为应美盛)公司产的数字运动传感器在国内非常流行,我用过它的两款,9250和6050.出于被国产芯片惯坏的 ...

  3. Vue.js Mixins 混入使用

    Mixins一般有两种用途: 1.在你已经写好了构造器后,需要增加方法或者临时的活动时使用的方法,这时用混入会减少源代码的污染. 2.很多地方都会用到的公用方法,用混入的方法可以减少代码量,实现代码重 ...

  4. 推荐系统 TOP K 评价指标

    目录 符号说明 示例数据 一.Hit Rate 二.Recall 三.NDCG 符号说明 \(top\_k\): 当前用户预测分最高的k个items,预测分由高到低排序 $pos$: 当前用户实际点击 ...

  5. XCTF练习题---WEB---view_source

    XCTF练习题---WEB---view_source flag:cyberpeace{662b1cf989a0a7999a5589290ce5a88e} 解题步骤: 1.观察题目,打开场景 2.根据 ...

  6. Python 迭代器、生成器、可迭代对象

    迭代器 1 #迭代器定义: 2 #类中得有__iter__和__next__两个方法 3 #__iter__方法放回对象本身,即:self(是迭代器对象) 4 #__next__方法,返回下一个数据, ...

  7. [STL] queue 队列 priority_queue 优先队列

  8. 服务器安全加固 - Linux

    一.账号和口令 1.1 禁用或删除无用账号 查看 /etc/passwd 文件查看是否有无用的账号,如果存在则删除,降低安全风险. 操作步骤: 使用命令 userdel <用户名> 删除不 ...

  9. vue - Vue路由(扩展)

    忙里偷闲,还在学校,趁机把后面的路由多出来的知识点学完 十.缓存路由组件 让不展示的路由组件保持挂载,不被销毁 在我们的前面案例有一个问题,都知道vue的路由当我们切换一个路由后,另一个路由就会被销毁 ...

  10. 138_Power BI&Power Pivot特殊半累加度量

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 半累加度量(semi-additive measure),在DAX建模分析的时候经常遇见:应用场景诸如银行存款. ...