一、Mapjoin案例

  1.需求:有两个文件,分别是订单表、商品表,

  订单表有三个属性分别为订单时间、商品id、订单id(表示内容量大的表),

  商品表有两个属性分别为商品id、商品名称(表示内容量小的表,用于加载到内存),

  要求结果文件为在订单表中的每一行最后添加商品id对应的商品名称。

  2.解决思路:

  将商品表加载到内存中,然后再map方法中将订单表中的商品id对应的商品名称添加到该行的最后,不需要Reducer,并在Driver执行类中设置setCacheFile和numReduceTask。

  3.代码如下:

public class CacheMapper extends Mapper<LongWritable, Text, Text, NullWritable>{

	HashMap<String, String> pdMap = new HashMap<>();
//1.商品表加载到内存
protected void setup(Context context) throws IOException { //加载缓存文件
BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("pd.txt"), "Utf-8")); String line; while(StringUtils.isNotEmpty(line = br.readLine()) ) { //切分
String[] fields = line.split("\t"); //缓存
pdMap.put(fields[0], fields[1]); } br.close(); } //2.map传输
@Override
protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, NullWritable>.Context context)
throws IOException, InterruptedException {
//获取数据
String line = value.toString(); //切割
String[] fields = line.split("\t"); //获取订单中商品id
String pid = fields[1]; //根据订单商品id获取商品名
String pName = pdMap.get(pid); //拼接数据
line = line + "\t" + pName; //输出
context.write(new Text(line), NullWritable.get());
}
} public class CacheDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException {
// 1.获取job信息
Configuration conf = new Configuration();
Job job = Job.getInstance(conf); // 2.获取jar包
job.setJarByClass(CacheDriver.class); // 3.获取自定义的mapper与reducer类
job.setMapperClass(CacheMapper.class); // 5.设置reduce输出的数据类型(最终的数据类型)
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class); // 6.设置输入存在的路径与处理后的结果路径
FileInputFormat.setInputPaths(job, new Path("c://table1029//in"));
FileOutputFormat.setOutputPath(job, new Path("c://table1029//out")); //加载缓存商品数据
job.addCacheFile(new URI("file:///c:/inputcache/pd.txt")); //设置一下reducetask的数量
job.setNumReduceTasks(0); // 7.提交任务
boolean rs = job.waitForCompletion(true);
System.out.println(rs ? 0 : 1);
}
}

  

二、Reducejoin案例

  1.需求:同上的两个数据文件,要求将订单表中的商品id替换成对应的商品名称。

  2.解决思路:封装TableBean类,包含属性:时间、商品id、订单id、商品名称、flag(flag用来判断是哪张表),

    使用Mapper读两张表,通过context对象获取切片对象,然后通过切片获取切片名称和路径的字符串来判断是哪张表,再将切片的数据封装到TableBean对象,最后以产品id为key、TableBean对象为value传输到Reducer端;

    Reducer接收数据后通过flag判断是哪张表,因为一个reduce中的所有数据的key是相同的,将商品表的商品id和商品名称读入到一个TableBean对象中,然后将订单表的中的数据读入到TableBean类型的ArrayList对象中,然后将ArrayList中的每个TableBean的商品id替换为商品名称,然后遍历该数组以TableBean为key输出。

  3.代码如下:

/**
* @author: PrincessHug
* @date: 2019/3/30, 2:37
* @Blog: https://www.cnblogs.com/HelloBigTable/
*/
public class TableBean implements Writable {
private String timeStamp;
private String productId;
private String orderId;
private String productName;
private String flag; public TableBean() {
} public String getTimeStamp() {
return timeStamp;
} public void setTimeStamp(String timeStamp) {
this.timeStamp = timeStamp;
} public String getProductId() {
return productId;
} public void setProductId(String productId) {
this.productId = productId;
} public String getOrderId() {
return orderId;
} public void setOrderId(String orderId) {
this.orderId = orderId;
} public String getProductName() {
return productName;
} public void setProductName(String productName) {
this.productName = productName;
} public String getFlag() {
return flag;
} public void setFlag(String flag) {
this.flag = flag;
} @Override
public void write(DataOutput out) throws IOException {
out.writeUTF(timeStamp);
out.writeUTF(productId);
out.writeUTF(orderId);
out.writeUTF(productName);
out.writeUTF(flag);
} @Override
public void readFields(DataInput in) throws IOException {
timeStamp = in.readUTF();
productId = in.readUTF();
orderId = in.readUTF();
productName = in.readUTF();
flag = in.readUTF();
} @Override
public String toString() {
return timeStamp + "\t" + productName + "\t" + orderId;
}
} public class TableMapper extends Mapper<LongWritable, Text,Text,TableBean> {
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//通过切片获取文件信息
FileSplit split = (FileSplit) context.getInputSplit();
String name = split.getPath().getName(); //获取一行数据、定义TableBean对象
String line = value.toString();
TableBean tb = new TableBean();
Text t = new Text(); //判断是哪一张表
if (name.contains("order.txt")){
String[] fields = line.split("\t");
tb.setTimeStamp(fields[0]);
tb.setProductId(fields[1]);
tb.setOrderId(fields[2]);
tb.setProductName("");
tb.setFlag("0");
t.set(fields[1]);
}else {
String[] fields = line.split("\t");
tb.setTimeStamp("");
tb.setProductId(fields[0]);
tb.setOrderId("");
tb.setProductName(fields[1]);
tb.setFlag("1");
t.set(fields[0]);
}
context.write(t,tb);
}
} public class TableReducer extends Reducer<Text,TableBean,TableBean, NullWritable> {
@Override
protected void reduce(Text key, Iterable<TableBean> values, Context context) throws IOException, InterruptedException {
//分别创建用来存储订单表和产品表的集合
ArrayList<TableBean> orderBean = new ArrayList<>();
TableBean productBean = new TableBean(); //遍历values,通过flag判断是产品表还是订单表
for (TableBean v:values){
if (v.getFlag().equals("0")){
TableBean tableBean = new TableBean();
try {
BeanUtils.copyProperties(tableBean,v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
orderBean.add(tableBean);
}else {
try {
BeanUtils.copyProperties(productBean,v);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
//拼接表
for (TableBean ob:orderBean) {
ob.setProductName(productBean.getProductName());
context.write(ob,NullWritable.get());
}
}
} public class TableDriver {
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
//job信息
Configuration conf = new Configuration();
Job job = Job.getInstance(conf); //jar包
job.setJarByClass(TableDriver.class); //Mapper、Reducer
job.setMapperClass(TableMapper.class);
job.setReducerClass(TableReducer.class); //Mapper输出数据类型
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(TableBean.class); //Reducer输出数据类型
job.setOutputKeyClass(TableBean.class);
job.setOutputValueClass(NullWritable.class); //输入输出路径
FileInputFormat.setInputPaths(job,new Path("G:\\mapreduce\\reducejoin\\in"));
FileOutputFormat.setOutputPath(job,new Path("G:\\mapreduce\\reducejoin\\out")); //提交任务
if (job.waitForCompletion(true)){
System.out.println("运行完成!");
}else {
System.out.println("运行失败!");
}
}
}

  

Mapjoin和Reducejoin案例的更多相关文章

  1. mapjoin与reducejoin

    一.mapjoin 1.Mapper类 package com.css.mapjoin; import java.io.BufferedReader; import java.io.FileInput ...

  2. 使用MapReduce实现join操作

     在关系型数据库中,要实现join操作是非常方便的,通过sql定义的join原语就可以实现.在hdfs存储的海量数据中,要实现join操作,可以通过HiveQL很方便地实现.不过HiveQL也是转化成 ...

  3. 【大数据】Hive学习笔记

    第1章 Hive基本概念 1.1 什么是Hive Hive:由Facebook开源用于解决海量结构化日志的数据统计. Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表, ...

  4. MapReduce(四) 典型编程场景(二)

    一.MapJoin-DistributedCache 应用 1.mapreduce join 介绍 在各种实际业务场景中,按照某个关键字对两份数据进行连接是非常常见的.如果两份数据 都比较小,那么可以 ...

  5. 工作中常见的hive语句总结

    hive的启动: 1.启动hadoop2.开启 metastore 在开启 hiveserver2服务nohup hive --service metastore >> log.out 2 ...

  6. 大数据技术之Hive

    第1章 Hive入门 1.1 什么是Hive Hive:由Facebook开源用于解决海量结构化日志的数据统计. Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提 ...

  7. MR案例:Reduce-Join

    问题描述:两种类型输入文件:address(地址)和company(公司)进行一对多的关联查询,得到地址名(例如:Beijing)与公司名(例如:Beijing JD.Beijing Red Star ...

  8. MapReduce之MapJoin案例

    @ 目录 使用场景 优点 具体办法:采用DistributedCache 案例 需求分析 代码实现 使用场景 Map Join 适用于一张表十分小.一张表很大的场景. 优点 思考:在Reduce 端处 ...

  9. MR案例:Map-Join

    适用场景:一张表十分小[key不可重复].一张表非常大. 用法:在Job提交时,首先将小表加载到 DistributedCache 分布式缓存中,然后从DistributeCache中读取小表解析成 ...

随机推荐

  1. 【LOJ6060】【2017 山东一轮集训 Day1 / SDWC2018 Day1】Set 线性基

    题目大意 给出 \(n\) 个非负整数,将数划分成两个集合,记为一号集合和二号集合.\(x_1\) 为一号集合中所有数的异或和,\(x_2\) 为二号集合中所有数的异或和.在最大化 \(x_1 + x ...

  2. MT【319】分段递推数列

    已知数列$ x_n $满足$ 0<x_1<x_2<\pi $,且\begin{equation*} x_{n+1}= \left\{ \begin{aligned}x_n+\sin ...

  3. Java大小写转化

    java大写转小写 public String toLowerCase(String str){ char[] chars = str.toCharArray(); for (int i = 0; i ...

  4. Java【第八篇】面向对象之高级类特性

    static 关键字 当我们编写一个类时,其实就是在描述其对象的属性和行为,而并没有产生实质上的对象,只有通过new关键字才会产生出对象,这时系统才会分配内存空间给对象,其方法才可以供外部调用.我们有 ...

  5. 计算机网络--差错检测(帧检验序列FCS计算方法)

    我们知道数据链路层广泛使用循环冗余检验CRC的检验技术 现在我们知道要发送的数据M=101001(长度为k=6)  在我们每次发送数据的时候需要在M后面添加一个N位的冗余码,一共发送(k+N)位数据 ...

  6. JS学习笔记Day11

    一.什么是事件对象(黑匣子) (一)事件: onclick ondblclick (二)当绑定对象的事件被触发时,所发生的所有详细信息都会保存在一个地方,这个地方称为事件对象 二.如何获取事件对象 ( ...

  7. 记一次504 Gateway Time-out

    使用curl请求是超时,查了下资料原来是端口被占用,造成了死锁,记录下 首先要知道为什么会出现死锁? 在我们访问页面的时候这个端口进程就已经被使用,当我们再在页面中curl请求其他页面因为没有其他的端 ...

  8. LFYZ-OJ ID: 1011 hanoi双塔问题

    思路 虽然每种大小盘子数量为2,但对总步数的影响只是一个简单的倍数关系而已,递推关系很容易可以总结出来:an=an-1+2+an-1=2(an-1+1),n=1时,a1=2.故递推的过程就是从a1=2 ...

  9. LFYZ-OJ ID: 1028 背包问题

    背包问题 题目描述 简单的背包问题.设有一个背包,可以放入的重量为s.现有n件物品,重量分别为w1,w2-,wn,(1≤i≤n)均为正整数,从n件物品中挑选若干件,使得放入背包的重量之和正好为s.找到 ...

  10. 第十节: 利用SQLServer实现Quartz的持久化和双机热备的集群模式 :

    背景: 默认情况下,Quartz.Net作业是持久化在内存中的,即 quartz.jobStore.type = "Quartz.Simpl.RAMJobStore, Quartz" ...