十二道MR习题 - 3 - 交集并集差集
题目
有两个文件A和B,两个文件中都有几百万行数字,现在需要找出A文件和B文件中数字集合的交集、并集、以及A对B的差集。
简单说一下思路:
这个问题关键在于key和value的设计。这里我将文件中的数字设置为key,将文件名称设置为value。这样在reduce阶段很容易就能找出A、B两个文件中数字的交并差集了。
并集就是reduce阶段能输出的全部记录;交集则需要做下过滤,即一个记录中的value需要同时有A、B两个文件的名称;差集则是文件名称集合中只包含A或B的记录。
看下用MapReduce是如何实现的:
package com.zhyea.dev; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.NullWritable;
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.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import java.io.IOException;
import java.util.Iterator; public class ContentCompare { public static class SplitterMapper extends Mapper<Object, Text, Text, Text> { private Text text = new Text(); @Override
public void map(Object key, Text value, Context context) {
try {
String fileName = ((FileSplit) context.getInputSplit()).getPath().getName();
text.set(fileName);
context.write(value, text);
} catch (Exception e) {
e.printStackTrace();
}
}
} public static class UnionReducer extends Reducer<Text, Text, Text, NullWritable> {
@Override
public void reduce(Text key, Iterable<Text> values, Context context) {
try {
context.write(key, NullWritable.get());
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static class InterReducer extends Reducer<Text, Text, Text, NullWritable> {
@Override
public void reduce(Text key, Iterable<Text> values, Context context) {
try {
Iterator<Text> itr = values.iterator();
boolean flagA = false;
boolean flagB = false;
while (itr.hasNext()) {
String s = itr.next().toString();
if (s.equals("B")) {
flagB = true;
}
if (s.equals("A")) {
flagA = true;
}
}
if (flagA && flagB) {
context.write(key, NullWritable.get());
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static class DiffAReducer extends Reducer<Text, Text, Text, NullWritable> {
@Override
public void reduce(Text key, Iterable<Text> values, Context context) {
try {
Iterator<Text> itr = values.iterator();
boolean flagA = false;
boolean flagB = false;
while (itr.hasNext()) {
String s = itr.next().toString();
if (s.equals("A")) {
flagA = true;
}
if (s.equals("B")) {
flagB = true;
}
}
if (flagA && !flagB) {
context.write(key, NullWritable.get());
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration conf = new Configuration(); Job job = Job.getInstance(conf, "content-compare");
job.setJarByClass(ContentCompare.class); job.setMapperClass(SplitterMapper.class);
job.setReducerClass(DiffAReducer.class); job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class); job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class); job.setNumReduceTasks(1); FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1])); System.exit(job.waitForCompletion(true) ? 0 : 1);
} }
用spark实现就简单的多了,这里我们很大程度上是受益于scala语法的简洁性:
package com.talkingdata.campaign import org.apache.hadoop.io.{LongWritable, Text}
import org.apache.hadoop.mapred.{FileSplit, InputSplit, TextInputFormat}
import org.apache.spark.rdd.HadoopRDD
import org.apache.spark.{SparkConf, SparkContext} object ContentCompare { def main(args: Array[String]): Unit = { val inputPath = args(0)
val outputPath = args(1)
val conf = new SparkConf().setAppName("content compare")
val sc = new SparkContext(conf) val data = sc.hadoopFile[LongWritable, Text, TextInputFormat](inputPath)
val hadoopRDD = data.asInstanceOf[HadoopRDD[LongWritable, Text]] hadoopRDD.mapPartitionsWithInputSplit[(String, String)](readFile)
.reduceByKey(_ + _)
.filter(p => p._2.length == 2)
.map(p => p._1)
.repartition(1)
.saveAsTextFile(outputPath) def readFile(inputSplit: InputSplit, itr: Iterator[(LongWritable, Text)]) = {
val fileName = inputSplit.asInstanceOf[FileSplit].getPath.getName
itr.map(p => (p._2.toString, fileName))
} } }
上面的代码中列出了计算交集的方法。并集实在是没什么好说的,读取文件后,reduce或distinct一下就能实现了。
要计算差集的话只需要调整下filter中的函数值就可以了:
hadoopRDD.mapPartitionsWithInputSplit[(String, String)](readFile)
.reduceByKey(_ + _)
.filter(p => p._2.length == 1 && p._2 == "A")
.map(p => p._1)
.repartition(1)
.saveAsTextFile(outputPath)
#############
十二道MR习题 - 3 - 交集并集差集的更多相关文章
- 十二道MR习题 - 2 - 多文件保存
题目: 需要将MR的执行结果保存到3个文件中,该怎么做. 又是一个送分题. 对于Hadoop的MapReduce来说只需要设置一下reduce任务的数量即可.MR的Job默认reduce数量是1,需要 ...
- 十二道MR习题 - 4 - TopN问题
题目: 有一个很大的文件,这文件中的内容全部都是数字,要求尝试从这个文件中找出最大的10个数字. 分析: 看起来像是一个比较简单的问题.不用大数据框架的话,也能比较轻易的实现:就是逐个读取文件中的每个 ...
- 十二道MR习题 – 1 – 排序
题目: 一个文件,大小约为100G.文件的每一行都是一个数字,要求对文件中的所有数字进行排序. 对于这个题目,了解过Hadoop的同学可以笑而不语了.即使用spark实现也是非常简单的事情. 先说下如 ...
- (java/javascript) list 交集 并集 差集 去重复并集
java list 交集 并集 差集 去重复并集 package com; import java.util.ArrayList; import java.util.Iterator; import ...
- Python 求两个文本文件以行为单位的交集 并集 差集
Python 求两个文本文件以行为单位的交集 并集 差集,来代码: s1 = set(open('a.txt','r').readlines()) s2 = set(open('b.txt','r') ...
- 如何求ArrayList集合的交集 并集 差集 去重复并集
需要用到List接口中定义的几个方法: addAll(Collection<? extends E> c) :按指定集合的Iterator返回的顺序将指定集合中的所有元素追加到此列表的末尾 ...
- spark之交集并集差集拉链
spark之交集并集差集拉链 def main(args: Array[String]): Unit = { val sparkConf = new SparkConf().setMaster(&qu ...
- java 两个list 交集 并集 差集 去重复并集
前提需要明白List是引用类型,引用类型采用引用传递. 我们经常会遇到一些需求求集合的交集.差集.并集.例如下面两个集合: List<String> list1 = new ArrayLi ...
- java list 交集 并集 差集 去重复并集
package com; import java.util.ArrayList;import java.util.Iterator;import java.util.List; public clas ...
随机推荐
- ubuntu16.04搭建jdk1.8运行环境
搭建环境:Ubuntu 16.04 ×64 JDK :jdk-8u171-linux-x64.tar.gz 首先下载linux对应的安装包下载地址:http://www.oracle.com/tech ...
- 用angular做的模糊搜索
今天大家来试一试用angular做一下简单的搜索功能吧: 首先我们需要写html的部分,我们需要设置几个条件,比如按什么来排序,按升序还是降序搜索,和一个文本框来设置模糊搜索: <nav> ...
- Centos7 下谷歌日志库GLog配置
1 glog下载地址 https://code.google.com/archive/p/google-glog/downloads glog-0.3.3.tar.gz 需要FQ,直接打不开 2 解压 ...
- 微信js获取地理位置
1.绑定域名 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”. 备注:登录后可在“开发者中心”查看对应的接口权限. 2.引入js文件 <script type=&q ...
- django自定义模板和过滤器
-自定义过滤器 -1 先app是不是已经在setting中注册 -2 在app下创建一个templatetags(****名字不能变***)的文件夹(模块) -3 在模块下创建一个py文件,名字随意: ...
- 安全必须作为基础,融入到产品开发过程——By Me
安全必须作为基础融入,让公司兄弟姐妹具备足够的安全意识,且逐渐具备必要的安全经验,带着安全思维去执行产品的架构设计.研发.测试.运维(甚至完整的产品生命周期),这是一种有远见.负责人的产品过程!! 下 ...
- ViewPager学习及使用(一)
一:基础篇 1.ViewPager的简介和作用ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的view1)ViewPager类直接继承了ViewGroup类,所有它 ...
- 算法题 21 findNSum (好未来,LeetCode,牛客网)
一.三数之和:LeetCode 15 给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. ...
- Part1.1 、RabbitMQ 操作使用
本节目录: 一.最基本的生产者消费者二.acknowledgment 消息不丢失的方法. 三.durable 消息不丢失 (消息持久化) 四.消息获取顺序 RabbitMQ安装. (1.1).ce ...
- Python:笔记(5)——错误、调试和测试
Python:笔记(5)——错误.调试和测试 错误处理 1.TRY语句 这个和Java中的语法是及其相似的,catach换成except. 说明:同样,不管有没有错误,fianlly都会执行的! 补充 ...