MapReduce--6--共同好友

MapReduce面试题1--求共同好友

1、数据格式

现在有一份数据如下:

A:B,C,D,F,E,O
B:A,C,E,K
C:F,A,D,I
D:A,E,F,L
E:B,C,D,M,L
F:A,B,C,D,E,O,M
G:A,C,D,E,F
H:A,C,D,E,O
I:A,O
J:B,O
K:A,C,D
L:D,E,F
M:E,F,G
O:A,H,I,J,K

数据以“:”为分割符,分隔符前部分是用户,后部分是用户的好友

A:B,C,D,F,E,O

为例:B,C,D,F,E,O全都为A的好友

2、题目:求所有用户之间的共同好友

最后的结果格式如下:比如用户A和用户B之间有共同好友:C,E

那么显示的结果是:

A-B	C E

3、解题思路分析

根据MapReduce的编程模型的特点,MapReduce编程分为Mapper阶段(任务的拆分)和Reducer阶段(结果的汇总)两个阶段。这两个阶段的业务逻辑,分别编写在Mapper组件的map方法和Reducer组件的reduce方法中。共同点,这两个阶段的业务逻辑方法都是接受key-value对,然后输出key-value对。
 

所以根据以上结果的格式,可以得知,reducer阶段输出的key-value中的key是A-B,value是C E,

那么value值(C E)怎么得来呢。?根据reduce(key,values,context)方法的特点得知,reduce方法其实接收到的参数是: key相同的一组key-value

也就意味着如果想得到

A-B    C E


这样的数据,必先得到如下这样的数据:

A-B    C
A-B    E


以上这种格式的数据的含义是:  C和E 是 A和B 的共同好友
现在再来解析单条数据, 以第一条为例子:


A-B    C


表示,C是A用户和B用户的共同好友,  也就是说 C是A的好友, C是B的好友, 所以C 才是A和B的共同好友。
那也就表示,如果能得到以下这样的数据:


C    A
C    B


那在MapReduce程序中,就能得到


C    A-B


然后倒过来不就是


A-B    C


么。 完美。
那么现在的问题(代号q1)就变成怎么得到如下的数据了:


C    A
C    B


事实上,这种格式的数据表示: C是A的好友, C是B的好友。
倒过来不就是说: A有好友C,B有好友C么?
现在请看原始数据:


A:B,C,D,F,E,O
这行数据的意思不就是表示A用户有好友B,C,D,F,E,O么?那么拆开就是:

 

A	B
A	C
A	D
A	F
A	E
A	O

这就能得到,q1问题处想要得到的数据了。

4、具体代码实现

具体的代码实现得分成两个MapReduce来实现:
先看第一个MapReduce程序的实现:

package com.ghgj.mazh.mapreduce.exercise.friend;
 
import java.io.IOException;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
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;
 
public class CommonFriends1MR {
 
	public static void main(String[] args) throws Exception {
 
		Configuration conf = new Configuration();
 
		Job job = Job.getInstance(conf);
		job.setJarByClass(CommonFriends1MR.class);
		job.setMapperClass(CommonFriends1MRMapper.class);
		job.setReducerClass(CommonFriends1MRReducer.class);
 
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(Text.class);
 
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
 
		Path inputPath = new Path("D:\\bigdata\\commonfriends\\input");
		Path outputPath = new Path("D:\\bigdata\\commonfriends\\output_111");
		FileSystem fs = FileSystem.get(conf);
		if (fs.exists(outputPath)) {
			fs.delete(outputPath, true);
		}
		FileInputFormat.setInputPaths(job, inputPath);
		FileOutputFormat.setOutputPath(job, outputPath);
 
		boolean res = job.waitForCompletion(true);
 
		System.exit(res ? 0 : 1);
	}
 
	public static class CommonFriends1MRMapper extends Mapper<LongWritable, Text, Text, Text> {
 
		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
			String line = value.toString();
			String[] tokens = line.split(":");
			String person = tokens[0];
			String[] friends = tokens[1].split(",");
 
			for (String f : friends) {
				context.write(new Text(f), new Text(person));
			}
		}
	}
 
	public static class CommonFriends1MRReducer extends Reducer<Text, Text, Text, Text> {
		@Override
		protected void reduce(Text friend, Iterable<Text> persons, Context context)
				throws IOException, InterruptedException {
 
			StringBuffer sb = new StringBuffer();
			for (Text p : persons) {
				sb.append(p).append("-");
			}
			context.write(friend, new Text(sb.toString()));
		}
	}
}

该MapReduce输出的结果的格式:

 

A    F-I-O-K-G-D-C-H-B-
B    E-J-F-A-
C    B-E-K-A-H-G-F-
D    H-C-G-F-E-A-K-L-
E    A-B-L-G-M-F-D-H-
F    C-M-L-A-D-G-
G    M-
H    O-
I    O-C-
J    O-
K    O-B-
L    D-E-
M    E-F-
O    A-H-I-J-F-

这种格式的数据表明:key是value中的任意两个用户的共同好友
比如:


A    F-I-O-K-G-D-C-H-B-


表示A是F和I的共同好友,A是F和O的共同好友,A是F和K的共同好友,............


还没有得到最终的结果,所以还需要一个MapReduce程序,来解析第一个MapReduce处理得到的结果数据,以得到最终的结果:
看具体代码实现:

package com.ghgj.mazh.mapreduce.exercise.friend;
 
import java.io.IOException;
import java.util.Arrays;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
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;
 
public class CommonFriends2MR {
 
	public static void main(String[] args) throws Exception {
 
		Configuration conf = new Configuration();
 
		Job job = Job.getInstance(conf);
		job.setJarByClass(CommonFriends2MR.class);
 
		job.setMapperClass(CommonFriends2MRMapper.class);
		job.setReducerClass(CommonFriends2MRReducer.class);
 
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(Text.class);
 
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
 
		Path inputPath = new Path("D:\\bigdata\\commonfriends\\output_111");
		Path outputPath = new Path("D:\\bigdata\\commonfriends\\last_output");
		FileSystem fs = FileSystem.get(conf);
		if (fs.exists(outputPath)) {
			fs.delete(outputPath, true);
		}
		FileInputFormat.setInputPaths(job, inputPath);
		FileOutputFormat.setOutputPath(job, outputPath);
 
		boolean res = job.waitForCompletion(true);
 
		System.exit(res ? 0 : 1);
	}
 
	public static class CommonFriends2MRMapper extends Mapper<LongWritable, Text, Text, Text> {
 
		/**
		 * A I-K-C-B-G-F-H-O-D- 
		 * B A-F-J-E- 
		 * C A-E-B-H-F-G-K-
		 */
		@Override
		protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
			String line = value.toString();
			String[] tokens = line.split("\t");
			String friend = tokens[0];
			String[] persons = tokens[1].split("-");
 
			Arrays.sort(persons);
			for (int i = 0; i < persons.length - 1; i++) {
				for (int j = i + 1; j < persons.length; j++) {
					context.write(new Text(persons[i] + "-" + persons[j]), new Text(friend));
				}
			}
		}
	}
 
	public static class CommonFriends2MRReducer extends Reducer<Text, Text, Text, Text> {
		@Override
		protected void reduce(Text person_pair, Iterable<Text> friends, Context context) throws IOException, InterruptedException {
 
			StringBuffer sb = new StringBuffer();
			for (Text f : friends) {
				sb.append(f).append(" ");
			}
			context.write(person_pair, new Text(sb.toString()));
		}
	}
}

第二个MapReduce程序执行得到的结果:
A-B    E C 
A-C    D F 
A-D    E F 
A-E    B C D 
A-F    C E O D B 
A-G    E F C D 
A-H    C D E O 
A-I     O 
A-J    O B 
A-K    C D 
A-L     F D E 
A-M    F E 
B-C     A 
B-D     A E 
B-E     C 
B-F     C A E 
B-G    E C A 
B-H    E C A 
B-I      A 
B-K     A C 
B-L     E 
B-M    E 
B-O    A K 
C-D    A F 
C-E    D 
C-F     A D 
C-G    A D F 
C-H    D A 
C-I      A 
C-K    A D 
C-L    D F 
C-M    F 
C-O    I A 
D-E    L 
D-F     A E 
D-G    E A F 
D-H    A E 
D-I      A 
D-K     A 
D-L     E F 
D-M    F E 
D-O     A 
E-F     D M C B 
E-G    C D 
E-H    C D 
E-J     B 
E-K    C D 
E-L    D 
F-G    D C A E 
F-H    A D O E C 
F-I     O A 
F-J    B O 
F-K    D C A 
F-L     E D 
F-M    E 
F-O    A 
G-H    D C E A 
G-I      A 
G-K    D A C 
G-L    D F E 
G-M    E F 
G-O    A 
H-I     O A 
H-J    O 
H-K    A C D 
H-L    D E 
H-M    E 
H-O    A 
I-J     O 
I-K     A 
I-O     A 
K-L    D 
K-O    A 
L-M    E F


以上的数据表示右边的value值就是左边的两个用户的共同好友。


至此,大功告成。ヾ(◍°∇°◍)ノ゙

--------------------- 
作者:中琦2513 
来源:CSDN 
原文:https://blog.csdn.net/zhongqi2513/article/details/78344509 
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值