共同好友案例
以下是博客的好友列表数据,冒号前是一个用户,冒号后是该用户的所有好友(数据中
的好友关系是单向的),求出哪些人两两之间有共同好友,及他俩的共同好友都有谁?
数据如下:
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
第一次先找出A、B、…是谁的好友
Mapper
public class SameFriendsFirstMapper extends Mapper<LongWritable, Text, Text, Text> {
Text k = new Text();
Text v = new Text();
@Override
protected void map (LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// A:B,C,D,F,E,O
// A的好友有B,C,D,F,E,O
// 找出X是谁的好友
// 输出如<B,A>
String line = value.toString();
String[] fields = line.split(":");
v.set(fields[0]);
if (fields.length > 1) {
String[] keyFields = fields[1].split(",");
for (String keyField : keyFields) {
k.set(keyField);
context.write(k, v);
}
}
}
}
Reducer
public class SameFriendsFirstReducer extends Reducer<Text, Text, Text, NullWritable> {
Text k = new Text();
@Override
protected void reduce (Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
List<String> list = new ArrayList<>();
for (Text value : values) {
list.add(value.toString());
}
k.set(key.toString() + ":" + String.join(",", list));
context.write(k, NullWritable.get());
}
}
第一次运行结果如下:
A:I,K,C,B,G,F,H,O,D
B:A,F,J,E
C:A,E,B,H,F,G,K
D:G,C,K,A,L,F,E,H
E:G,M,L,H,A,F,B,D
F:L,M,D,C,G,A
G:M
H:O
I:O,C
J:O
K:B
L:D,E
M:E,F
O:A,H,I,J,F
Mapper
public class SameFriendsSecondMapper extends Mapper<LongWritable, Text, Text, Text> {
Text k = new Text();
Text v = new Text();
@Override
protected void map (LongWritable key, Text value, Context context) throws IOException, InterruptedException {
// A:I,K,C,B,G,F,H,O,D
// A是I,K,C,B,G,F,H,O,D的好友
// 输出如<I-K, A>
String line = value.toString();
String[] fields = line.split(":");
v.set(fields[0]);
if (fields.length > 1) {
String[] keyPreFields = fields[1].split(",");
for (int i = 0; i < keyPreFields.length - 1; i++) {
String first = keyPreFields[i];
for (int j = i + 1; j < keyPreFields.length; j++) {
String second = keyPreFields[j];
// 防止出现A-D和D-A的情况
if (first.compareToIgnoreCase(second) < 0) {
k.set(first + "-" + second);
} else {
k.set(second + "-" + first);
}
context.write(k, v);
}
}
}
}
}
Reducer
public class SameFriendsSecondReducer extends Reducer<Text, Text, Text, Text> {
Text v = new Text();
@Override
protected void reduce (Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
List<String> list = new ArrayList<>();
for (Text value : values) {
list.add(value.toString());
}
v.set(String.join(" ", list));
context.write(key, v);
}
}
第二次运行结果:
A-B C E
A-C D F
A-D F E
A-E B D C
A-F C B O D E
A-G F D E C
A-H D O E C
A-I O
A-J O B
A-K D C
A-L E D F
A-M F E
B-C A
B-D E A
B-E C
B-F E A C
B-G C A E
B-H E C A
B-I A
B-K C A
B-L E
B-M E
B-O A
C-D F A
C-E D
C-F D A
C-G D F A
C-H A D
C-I A
C-K D A
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 E A
D-I A
D-K A
D-L E F
D-M E F
D-O A
E-F B M D C
E-G D C
E-H D C
E-J B
E-K D C
E-L D
F-G C D A E
F-H A E O C D
F-I O A
F-J O B
F-K A C D
F-L E D
F-M E
F-O A
G-H A D E C
G-I A
G-K C A D
G-L F D E
G-M F E
G-O A
H-I A O
H-J O
H-K A D C
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 F E