您的位置:首页 > 其它

MapReduce--6--求共同好友

2017-10-25 18:08 477 查看

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,E,F,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值就是左边的两个用户的共同好友。

至此,大功告成。ヾ(◍°∇°◍)ノ゙
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息