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
求:哪两个人之间有共同好友,以及他们的共同好友都有哪些人。
2.解题思路
2.1 第一步:map阶段
读取一行数据,如:A:B,C,D,F,E,O。按照冒号进行切分,冒号前面是我们的用户,冒号后面是我们的好友列表。然后将好友列表继续按照逗号进行切分。
好友列表按照逗号一切分,就形成如下的数组。
String[] arrays = ["B,C,D,F,E,O"]
然后循环遍历这个数组,把B当成一个key,把A当成一个value往外发,把C当成一个key,把A当成一个value往外发,以此类推。
然后输出<B,A><C,A><D,A><F,A><E,A><O,A>。
再读一行E:B,C,D,M,L,输出<B,E><C,E><D,E><M,E><L,E>。
2.2 第二步:reduce阶段
到了reduce阶段,相同key的value发送到同一个reduce当中。
map阶段发出去的数据
key2 | value2 |
---|---|
B | A |
C | A |
D | A |
F | A |
E | A |
O | A |
B | E |
数据到了reduce,就会变成如下结构:
<A-E,B>
3.代码实现
map阶段
public static class ComonsFriendsStepOneMapper extends Mapper<LongWritable,Text,Text,Text>{
//输入数据如下格式:A:B,C,D,F,E,O
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
//value.toString()得到我们一行数据
//然后按冒号一切,得到一个数组,数组下标0是我们的用户,下标1是我们的好友列表
String[] split = value.toString().split(":");
String person = split[0];
//对我们的好友列表继续按照逗号切
String[] friends = split[1].split(",");
//循环迭代我们的好友列表
for (String friend : friends) {
context.write(new Text(friend),new Text(person));
}
}
}
reduce阶段
public static class ComonsFriendsStepOneReducer extends Reducer<Text,Text,Text,Text>{
//reduce接收到的数据 B [A,E]
//B是我们的好友,集合里面装的是我们的多个用户
//将数据最终转换成这样的形式进行输出,A-B-E-F-G-H-K C,遍历,拼接字符串就行了
@Override
protected void reduce(Text friend, Iterable<Text> persons, Context context) throws IOException, InterruptedException {
StringBuffer buffer = new StringBuffer();
for (Text person : persons) {
buffer.append(person).append("-");
}
context.write(friend,new Text(buffer.toString()));
}
}