java使用hadoop實(shí)現(xiàn)關(guān)聯(lián)商品統(tǒng)計(jì)
最近幾天一直在看Hadoop相關(guān)的書籍,目前稍微有點(diǎn)感覺,自己就仿照著WordCount程序自己編寫了一個(gè)統(tǒng)計(jì)關(guān)聯(lián)商品。
需求描述:
根據(jù)超市的銷售清單,計(jì)算商品之間的關(guān)聯(lián)程度(即統(tǒng)計(jì)同時(shí)買A商品和B商品的次數(shù))。
數(shù)據(jù)格式:
超市銷售清單簡(jiǎn)化為如下格式:一行表示一個(gè)清單,每個(gè)商品采用 "," 分割,如下圖所示:

需求分析:
采用hadoop中的mapreduce對(duì)該需求進(jìn)行計(jì)算。
map函數(shù)主要拆分出關(guān)聯(lián)的商品,輸出結(jié)果為 key為商品A,value為商品B,對(duì)于第一條三條結(jié)果拆分結(jié)果如下圖所示:

這里為了統(tǒng)計(jì)出和A、B兩件商品想關(guān)聯(lián)的商品,所以商品A、B之間的關(guān)系輸出兩條結(jié)果即 A-B、B-A。
reduce函數(shù)分別對(duì)和商品A相關(guān)的商品進(jìn)行分組統(tǒng)計(jì),即分別求value中的各個(gè)商品出現(xiàn)的次數(shù),輸出結(jié)果為key為商品A|商品B,value為該組合出現(xiàn)的次數(shù)。針對(duì)上面提到的5條記錄,對(duì)map輸出中key值為R的做下分析:
通過map函數(shù)的處理,得到如下圖所示的記錄:

reduce中對(duì)map輸出的value值進(jìn)行分組計(jì)數(shù),得到的結(jié)果如下圖所示

將商品A B作為key,組合個(gè)數(shù)作為value輸出,輸出結(jié)果如下圖所示:

對(duì)于需求的實(shí)現(xiàn)過程的分析到目前就結(jié)束了,下面就看下具體的代碼實(shí)現(xiàn)
代碼實(shí)現(xiàn):
關(guān)于代碼就不做詳細(xì)的介紹,具體參照代碼之中的注釋吧。
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類,實(shí)現(xiàn)數(shù)據(jù)的預(yù)處理
* 輸出結(jié)果key為商品A value為關(guān)聯(lián)商品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(",");
//兩兩組合,構(gòu)成一條記錄
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;
}
//輸出結(jié)果
context.write(new Text(vs[i]), new Text(vs[j]));
context.write(new Text(vs[j]), new Text(vs[i]));
}
}
}
}
}
/**
* reduce類,實(shí)現(xiàn)數(shù)據(jù)的計(jì)數(shù)
* 輸出結(jié)果key 為商品A|B value為該關(guān)聯(lián)次數(shù)
* @author lulei
*/
public static class ReduceT extends Reducer<Text, Text, Text, IntWritable> {
private int count;
/**
* 初始化
*/
public void setup(Context context) {
//從參數(shù)中獲取最小記錄個(gè)數(shù)
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統(tǒng)計(jì)B商品的次數(shù)
for (Text value : values) {
String valueStr = value.toString();
if (hashMap.containsKey(valueStr)) {
hashMap.put(valueStr, hashMap.get(valueStr) + 1);
} else {
hashMap.put(valueStr, 1);
}
}
//將結(jié)果輸出
for (Entry<String, Integer> entry : hashMap.entrySet()) {
if (entry.getValue() >= this.count) {//只輸出次數(shù)不小于最小值的
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();
}
}
}
上傳運(yùn)行:
將程序打包成jar文件,上傳到機(jī)群之中。將測(cè)試數(shù)據(jù)也上傳到HDFS分布式文件系統(tǒng)中。
命令運(yùn)行截圖如下圖所示:

運(yùn)行結(jié)束后查看相應(yīng)的HDFS文件系統(tǒng),如下圖所示:

到此一個(gè)完整的mapreduce程序就完成了,關(guān)于hadoop的學(xué)習(xí),自己還將繼續(xù)~感謝閱讀,希望能幫助到大家,謝謝大家對(duì)本站的支持!
- java結(jié)合HADOOP集群文件上傳下載
- Java訪問Hadoop分布式文件系統(tǒng)HDFS的配置說明
- Java執(zhí)行hadoop的基本操作實(shí)例代碼
- 深入淺析Java Object Serialization與 Hadoop 序列化
- hadoop中實(shí)現(xiàn)java網(wǎng)絡(luò)爬蟲(示例講解)
- Java/Web調(diào)用Hadoop進(jìn)行MapReduce示例代碼
- Hadoop運(yùn)行時(shí)遇到j(luò)ava.io.FileNotFoundException錯(cuò)誤的解決方法
- hadoop運(yùn)行java程序(jar包)并運(yùn)行時(shí)動(dòng)態(tài)指定參數(shù)
- java實(shí)現(xiàn)對(duì)Hadoop的操作
- 利用Java連接Hadoop進(jìn)行編程
相關(guān)文章
idea中創(chuàng)建多module的maven工程的方法
這篇文章主要介紹了idea中創(chuàng)建多module的maven工程的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-10-10
SpringBoot集成圖片驗(yàn)證碼框架easy-captcha的詳細(xì)過程
本文介紹了如何將Easy-Captcha框架集成到SpringBoot項(xiàng)目中,實(shí)現(xiàn)圖片驗(yàn)證碼功能,Easy-Captcha是一款輕量級(jí)的開源驗(yàn)證碼框架,通過簡(jiǎn)潔的API和高度可定制性,可以快速實(shí)現(xiàn)驗(yàn)證碼功能,文章詳細(xì)介紹了如何配置、生成和展示驗(yàn)證碼,并提供了Easy-Captcha的GitHub地址2025-03-03
SpringBoot項(xiàng)目集成日志的實(shí)現(xiàn)方法
這篇文章主要介紹了SpringBoot項(xiàng)目集成日志的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-02-02
Java后端調(diào)用微信支付和支付寶支付的詳細(xì)步驟
這篇文章主要介紹了Java后端如何調(diào)用微信支付和支付寶支付,涵蓋了基本概念、配置步驟、代碼示例以及注意事項(xiàng),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-04-04
java代碼實(shí)現(xiàn)銀行管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java代碼實(shí)現(xiàn)銀行管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12
Java簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸
下面小編就為大家?guī)硪黄狫ava簡(jiǎn)單實(shí)現(xiàn)對(duì)一串?dāng)?shù)字采用相應(yīng)的加密策略后傳輸。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09
Spring?Mvc中CommonsMultipartFile的特性實(shí)例詳解
這篇文章主要給大家介紹了關(guān)于Spring?Mvc中CommonsMultipartFile特性的相關(guān)資料,SpringMVC擁有強(qiáng)大的靈活性,非侵入性和可配置性,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-11-11

