hadoopMapReduce运营商案例关于用户基站停留数据统计

实验要求

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

用户的手机,连接到不同的基站会产生一条记录。
数据格式为:用户标识 设备标识 基站位置 通讯的日期 通讯时间
example: 0000009999 0054785806 00000089 2016-02-21 21:55:37

需要得到的数据格式为:
用户标识 时段 基站位置 停留时间
example: 0000000001 09-18 00000003 15
用户0000000001在09-18点这个时间段在基站00000003停留了15分钟

程序运行支持传入时间段,比如”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,依次类推,所有的时间都获取到。再把时间累加起来,就可以获取到总的时间。

代码实现

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
{
    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
{
    @Override
    protected void reduce(Text key, Iterable values, Context context) throws IOException, InterruptedException
    {
        List valueList = new LinkedList();//基于链表的动态数组

        //Map是一种把键对象和值对象映射的集合,TreeMap是一个有序的key-value集合,
        //它是通过红黑树实现的,TreeMap中的元素默认按照key的自然排序排列
        Map residenceTimeMap = new TreeMap();

        for(Text value : values)
        {
            String item = value.toString();
            valueList.add(item);//"基站位置-访问时间"的集合
        }

        if(valueList == null || valueList.size() () {//匿名内部类
            @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 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;
    }
}

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

Original: https://www.cnblogs.com/cenjw/p/hadoop-mapReduce-operator-case.html
Author: micromatrix
Title: hadoopMapReduce运营商案例关于用户基站停留数据统计

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/712484/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • VSCodeUserSetup-x64-1.67.2

    https://vscode.cdn.azure.cn/stable/379476f0e13988d90fab105c5c19e7abc8b1dea8/VSCode-win32-x…

    技术杂谈 2023年6月1日
    095
  • PyInstaller 打包 python程序成exe

    主题是使用PyInstaller 打包python时遇到一些问题以及解决方案,其中将要打包的程序是用tensorflow做的LSTM算法,这里不会涉及这个算法详解。 本地环境:wi…

    技术杂谈 2023年6月21日
    081
  • 表单的子元素可不在form标签内

    表单是网页用于向服务器发送数据的元素。其用法类似下面: form标签对及其内部的所有子元素共同组成了表单。提交表单时,浏览器会将form标签对内所有具有name属性的标签的键值提交…

    技术杂谈 2023年7月23日
    060
  • Python自动化办公:读取Excel数据并批量生成合同,高效办公,快速回家

    前言 在我们的工作中,面临着大量的重复性工作,通过人工方式处理往往耗时耗力易出错。而Python在自动化办公方面具有极大的优 势,可以解决我们工作中遇到的很多重复性问题,分分钟搞定…

    技术杂谈 2023年6月21日
    087
  • Parsing error: Unexpected token < at … Vue CLI3

    在使用vue cli3的时候,遇到如下问题: 查阅了许多网站,都不能解决此问题,最后,在 https://stackoverflow.com/questions/53601579/…

    技术杂谈 2023年6月1日
    067
  • kettle中变量的设置和使用介绍

    有没有能统一管理一个参数,然后让所有的transformation和job都可以读到呢? 答案是有 1.首先,打开.kettlekettle.properties(个人主机是:C:…

    技术杂谈 2023年5月31日
    096
  • HTB靶场记录之Arctic

    这次的靶机是windows靶机。建议用MSF做前期的getshell,这样方便点。提权部分可能要手工编造PowerShell脚本传文件。 2、信息收集 还是先用nmap进行一波端口…

    技术杂谈 2023年5月31日
    084
  • 【cartographerros】九:建图和定位

    通过前面的介绍了,我们可以自己实现数据的发布,然后在cartographer进行建图和定位,并调整参数查看效果。本节就将介绍在cartographer用自己的数据进行建图和定位(在…

    技术杂谈 2023年7月24日
    078
  • c#代码技巧

    1.#region #endregion 1.#region 是一个分块预处理命令,主要用于编辑代码分段,在编译时会自动屏蔽,同时该指令可以使代码在VS代码编辑器中折叠或展开; 2…

    技术杂谈 2023年7月24日
    046
  • 接口和抽象类是否有构造方法

    先上结论: 接口没有,抽象类可以有。 甚至于有其他的区别: 接口不能有方法体,抽象类可以有 (仅限java8以前) 接口不能有静态方法,抽象类可以有 (仅限java8以前) 接口中…

    技术杂谈 2023年7月25日
    052
  • Clickhouse的MergeTree表引擎存储结构

    MergeTree存储的文件结构 一张数据表被分成几个data part,每个data part对应文件系统中的一个目录。通过以下SQL可以查询data parts的信息。 sel…

    技术杂谈 2023年7月24日
    083
  • Linux进程调度器

    完全公平调度器 用黑体标出的是文章的主线,未用黑体标出的内容是对黑体内容的解释或注解。 每次调用调度器时,它会挑选具有最高等待时间的进程,把CPU提供给该进程。如果经常发生这种情况…

    技术杂谈 2023年7月24日
    075
  • 2022.21 Web页面和本地程序通信的方法

    因为安全限制,web页面不能直接操作本地电脑资源,因此一些访问本地文件或操作本地设备之类的操作需要客户端本地程序来做,这就涉及到web页面与客户端电脑本地程序通信交互。 以前主流浏…

    技术杂谈 2023年5月30日
    084
  • vue总是报错:Trailing spaces not allowed

    翻译: Trailing spaces not allowed:不允许尾随空格 1-报错: 2-解决: 你的某些行的空格多了,删掉就行了 以我的截图为例 代码12行出错 选中12行…

    技术杂谈 2023年6月1日
    092
  • 简单实现一个快速传输电子书到kindle的小项目

    前言 最近翻出来好久没有看的kindle,准备继续我的阅读之路。当然,也是因为发现了一个非常好的获取电子书资源的网站,又燃起了我的阅读兴趣。 然而,往kindle里传输电子书的方式…

    技术杂谈 2023年7月25日
    082
  • antv g6

    Original: https://www.cnblogs.com/lexus/p/9440428.htmlAuthor: lexusTitle: antv g6

    技术杂谈 2023年5月30日
    088
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球