转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/40184581

近期几天一直在看hadoop相关的书籍,眼下略微有点感觉,自己就仿照着WordCount程序自己编写了一个统计关联商品。

需求描写叙述:

依据超市的销售清单,计算商品之间的关联程度(即统计同一时候买A商品和B商品的次数)。

数据格式:

超市销售清单简化为例如以下格式:一行表示一个清单,每一个商品採用 "," 切割,例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2ppbWFubWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

需求分析:

採用hadoop中的mapreduce对该需求进行计算。

map函数主要拆分出关联的商品,输出结果为 key为商品A,value为商品B,对于第一条三条结果拆分结果例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2ppbWFubWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

这里为了统计出和A、B两件商品想关联的商品。所以商品A、B之间的关系输出两条结果即 A-B、B-A。

reduce函数分别对和商品A相关的商品进行分组统计,即分别求value中的各个商品出现的次数,输出结果为key为商品A|商品B。value为该组合出现的次数。针对上面提到的5条记录,对map输出中key值为R的做下分析:

通过map函数的处理,得到例如以下图所看到的的记录:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2ppbWFubWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

reduce中对map输出的value值进行分组计数,得到的结果例如以下图所看到的

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb2ppbWFubWFu/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

将商品A B作为key,组合个数作为value输出,输出结果例如以下图所看到的:

对于需求的实现过程的分析到眼下就结束了。以下就看下详细的代码实现

代码实现:

关于代码就不做具体的介绍。具体參照代码之中的凝视吧。

package com;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map.Entry; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner; public class Test extends Configured implements Tool{ /**
* map类,实现数据的预处理
* 输出结果key为商品A value为关联商品B
* @author lulei
*/
public static class MapT extends Mapper<LongWritable, Text, Text, Text> {
public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException{
String line = value.toString();
if (!(line == null || "".equals(line))) {
//切割商品
String []vs = line.split(",");
//两两组合。构成一条记录
for (int i = 0; i < (vs.length - 1); i++) {
if ("".equals(vs[i])) {//排除空记录
continue;
}
for (int j = i+1; j < vs.length; j++) {
if ("".equals(vs[j])) {
continue;
}
//输出结果
context.write(new Text(vs[i]), new Text(vs[j]));
context.write(new Text(vs[j]), new Text(vs[i]));
}
}
}
}
} /**
* reduce类,实现数据的计数
* 输出结果key 为商品A|B value为该关联次数
* @author lulei
*/
public static class ReduceT extends Reducer<Text, Text, Text, IntWritable> {
private int count; /**
* 初始化
*/
public void setup(Context context) {
//从參数中获取最小记录个数
String countStr = context.getConfiguration().get("count");
try {
this.count = Integer.parseInt(countStr);
} catch (Exception e) {
this.count = 0;
}
}
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException{
String keyStr = key.toString();
HashMap<String, Integer> hashMap = new HashMap<String, Integer>();
//利用hash统计B商品的次数
for (Text value : values) {
String valueStr = value.toString();
if (hashMap.containsKey(valueStr)) {
hashMap.put(valueStr, hashMap.get(valueStr) + 1);
} else {
hashMap.put(valueStr, 1);
}
}
//将结果输出
for (Entry<String, Integer> entry : hashMap.entrySet()) {
if (entry.getValue() >= this.count) {//仅仅输出次数不小于最小值的
context.write(new Text(keyStr + "|" + entry.getKey()), new IntWritable(entry.getValue()));
}
}
}
} @Override
public int run(String[] arg0) throws Exception {
// TODO Auto-generated method stub
Configuration conf = getConf();
conf.set("count", arg0[2]); Job job = new Job(conf);
job.setJobName("jobtest"); job.setOutputFormatClass(TextOutputFormat.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class); job.setMapperClass(MapT.class);
job.setReducerClass(ReduceT.class); FileInputFormat.addInputPath(job, new Path(arg0[0]));
FileOutputFormat.setOutputPath(job, new Path(arg0[1])); job.waitForCompletion(true); return job.isSuccessful() ? 0 : 1; } /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
if (args.length != 3) {
System.exit(-1);
}
try {
int res = ToolRunner.run(new Configuration(), new Test(), args);
System.exit(res);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

上传执行:

将程序打包成jar文件,上传到机群之中。

将測试数据也上传到HDFS分布式文件系统中。

命令执行截图例如以下图所看到的:

执行结束后查看对应的HDFS文件系统,例如以下图所看到的:

到此一个完整的mapreduce程序就完毕了,关于hadoop的学习。自己还将继续~

使用hadoop实现关联商品统计的更多相关文章

  1. 基于Hadoop的地震数据分析统计

    源码下载地址:http://download.csdn.net/detail/huhui_bj/5645641 opencsv下载地址:http://download.csdn.net/detail/ ...

  2. 使用bash关联数组统计单词

    使用bash关联数组统计单词 从bash 4开始支持关联数组,使用前需要声明,即 declare -A map map[key1]=value1 map[key2]=value2 map=([key1 ...

  3. Hadoop Mapreduce 案例 wordcount+统计手机流量使用情况

    mapreduce设计思想 概念:它是一个分布式并行计算的应用框架它提供相应简单的api模型,我们只需按照这些模型规则编写程序,即可实现"分布式并行计算"的功能. 案例一:word ...

  4. Hadoop入门实例——WordCount统计单词

    首先要说明的是运行Hadoop需要jdk1.6或以上版本,如果你还没有搭建好Hadoop集群,请参考我的另一篇文章: Linux环境搭建Hadoop伪分布模式 马上进入正题. 1.启动Hadoop集群 ...

  5. hadoop fs:du & count统计hdfs文件(目录下文件)大小的用法

    hadoop fs 更多用法,请参考官网:http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_shell.html 以下是我的使用hadoop fs -du统计文 ...

  6. 初学Hadoop之中文词频统计

    1.安装eclipse 准备 eclipse-dsl-luna-SR2-linux-gtk-x86_64.tar.gz 安装 1.解压文件. 2.创建图标. ln -s /opt/eclipse/ec ...

  7. 初学Hadoop之WordCount词频统计

    1.WordCount源码 将源码文件WordCount.java放到Hadoop2.6.0文件夹中. import java.io.IOException; import java.util.Str ...

  8. 023_数量类型练习——Hadoop MapReduce手机流量统计

    1) 分析业务需求:用户使用手机上网,存在流量的消耗.流量包括两部分:其一是上行流量(发送消息流量),其二是下行流量(接收消息的流量).每种流量在网络传输过程中,有两种形式说明:包的大小,流量的大小. ...

  9. Eclipse上运行第一个Hadoop实例 - WordCount(单词统计程序)

    需求 计算出文件中每个单词的频数.要求输出结果按照单词的字母顺序进行排序.每个单词和其频数占一行,单词和频数之间有间隔. 比如,输入两个文件,其一内容如下: hello world hello had ...

随机推荐

  1. <转>MYSQL数据库数据拆分之分库分表总结

    数据存储演进思路一:单库单表 单库单表是最常见的数据库设计,例如,有一张用户(user)表放在数据库db中,所有的用户都可以在db库中的user表中查到. 数据存储演进思路二:单库多表 随着用户数量的 ...

  2. int各种数据类型的表示范围

    计算方法:1.正数部分数部分:2^(字节数*8-1)-1 2.负数部分:-(2^(字节数*8-1)+1) unsign int:正数部分*2+1

  3. POJ 1392 Ouroboros Snake(数位欧拉)

    题目链接:http://poj.org/problem?id=1392 题目大意:题意看的我头痛,其实跟HDU2894差不多,但是这题要求输出这条路径上第k个数,而不是输出路径. 解题思路:也跟HDU ...

  4. Js数组的常用的方法概述

    学习JS的同学们,也曾对数组进行学习掌握,所以我也把数组中常用的方法列举下来,相互学习 不多废话,直接上正文 .                 快乐的分割线... 一.对象继承的方法 数组是一种特殊 ...

  5. 常用开放api【长期更新】

    获取时间: 苏宁:http://quan.suning.com/getSysTime.do 淘宝:http://api.m.taobao.com/rest/api3.do?api=mtop.commo ...

  6. 113. 路径总和 II

    给定一个二叉树和一个目标和,找到所有从根节点到叶子节点路径总和等于给定目标和的路径. 说明: 叶子节点是指没有子节点的节点. 示例:给定如下二叉树,以及目标和 sum = 22, 5 / \ 4 8 ...

  7. 洛谷P1291 [SHOI2002]百事世界杯之旅 [数学期望]

    题目传送门 百事世界杯之旅 题目描述 “……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字.只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听, ...

  8. Array.reduce()方法的使用

    起因是学习异步函数的串行与并行写法时,发现reduce方法可以简化写法,然后看到一篇博客里面这样一段代码: var array = [1, [2, [3, 4], 5], 6]; function f ...

  9. Unity 游戏开发技巧集锦之使用cookie类型的纹理模拟云层的移动

    Unity 游戏开发技巧集锦之使用cookie类型的纹理模拟云层的移动 使用cookie类型的纹理模拟云层的移动 现实生活中,当阳光直射大地,而天空中又有很多云时,云层的影子总是会投射在大地上,风吹着 ...

  10. 2017/11/6 Leetcode 日记

    2017/11/6 Leetcode 日记 344. Reverse String Write a function that takes a string as input and returns ...