使用hadoop实现关联商品统计
转载请注明出处: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实现关联商品统计的更多相关文章
- 基于Hadoop的地震数据分析统计
源码下载地址:http://download.csdn.net/detail/huhui_bj/5645641 opencsv下载地址:http://download.csdn.net/detail/ ...
- 使用bash关联数组统计单词
使用bash关联数组统计单词 从bash 4开始支持关联数组,使用前需要声明,即 declare -A map map[key1]=value1 map[key2]=value2 map=([key1 ...
- Hadoop Mapreduce 案例 wordcount+统计手机流量使用情况
mapreduce设计思想 概念:它是一个分布式并行计算的应用框架它提供相应简单的api模型,我们只需按照这些模型规则编写程序,即可实现"分布式并行计算"的功能. 案例一:word ...
- Hadoop入门实例——WordCount统计单词
首先要说明的是运行Hadoop需要jdk1.6或以上版本,如果你还没有搭建好Hadoop集群,请参考我的另一篇文章: Linux环境搭建Hadoop伪分布模式 马上进入正题. 1.启动Hadoop集群 ...
- hadoop fs:du & count统计hdfs文件(目录下文件)大小的用法
hadoop fs 更多用法,请参考官网:http://hadoop.apache.org/docs/r1.0.4/cn/hdfs_shell.html 以下是我的使用hadoop fs -du统计文 ...
- 初学Hadoop之中文词频统计
1.安装eclipse 准备 eclipse-dsl-luna-SR2-linux-gtk-x86_64.tar.gz 安装 1.解压文件. 2.创建图标. ln -s /opt/eclipse/ec ...
- 初学Hadoop之WordCount词频统计
1.WordCount源码 将源码文件WordCount.java放到Hadoop2.6.0文件夹中. import java.io.IOException; import java.util.Str ...
- 023_数量类型练习——Hadoop MapReduce手机流量统计
1) 分析业务需求:用户使用手机上网,存在流量的消耗.流量包括两部分:其一是上行流量(发送消息流量),其二是下行流量(接收消息的流量).每种流量在网络传输过程中,有两种形式说明:包的大小,流量的大小. ...
- Eclipse上运行第一个Hadoop实例 - WordCount(单词统计程序)
需求 计算出文件中每个单词的频数.要求输出结果按照单词的字母顺序进行排序.每个单词和其频数占一行,单词和频数之间有间隔. 比如,输入两个文件,其一内容如下: hello world hello had ...
随机推荐
- web项目更改文件后缀,隐藏编程语言
从Java EE5.0开始,<servlet-mapping>标签就可以配置多个<url-pattern>.例如可以同时将urlServlet配置一下多个映射方式: <s ...
- CSRF攻击的应对之道
CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,该攻击可以在受害者毫不知情的情况下以受害者名义伪造请求发送给受攻击站点,从而在并未授权的情况下执 ...
- IEEEXtreme 10.0 - Painter's Dilemma
这是 meelo 原创的 IEEEXtreme极限编程比赛题解 Xtreme 10.0 - Painter's Dilemma 题目来源 第10届IEEE极限编程大赛 https://www.hack ...
- 五、oracle 表管理
一.表名和列名的命名规则1).必须以字母开头2).长度不能超过30个字符3).不能使用oracle的保留字4).只能使用如下字符 a-z,a-z,0-9,$,#等 二.数据类型1).字符类char 长 ...
- Java-redis分布式锁 抢购秒杀系统 实现
一.使用分布式锁要满足的几个条件: 系统是一个分布式系统(关键是分布式,单机的可以使用ReentrantLock或者synchronized代码块来实现) 共享资源(各个系统访问同一个资源,资源的载体 ...
- python动态获取对象的属性和方法 (转)
转自未知,纯个人笔记使用 首先通过一个例子来看一下本文中可能用到的对象和相关概念. #coding:utf-8 import sys def foo():pass class Cat(object): ...
- 爱奇艺全国高校算法大赛初赛C
区间$dp$. 倒着考虑这件事件,肯定有最后一个取走的数字,假设是$a[k]$,那么最后一次取走的价值肯定是$a[0]*a[k]*a[n+1]$,之前取走的价值和为$[1,k-1]$的价值加上$[k+ ...
- SCU 4441 Necklace
最长上升子序列,枚举. 因为$10000$最多只有$10$个,所以可以枚举采用哪一个$10000$,因为是一个环,所以每次枚举到一个$10000$,可以把这个移到最后,然后算从前往后的$LIS$和从后 ...
- c++ getline()
#include <iostream>#include <string> int main (){ std::string name; std::cout << & ...
- Python函数系列-Random
import random i = int(input('输入第一个数:')) j = int(input('输入第二个数:')) l = int(input('输入需要产生的个数:')) k=0 w ...