【hadoop】MapReduce寻找博主共同好友

花了2个星期刷完了尚硅谷hadoop课程,虽然是第二次学习hadoop,但是收获也非常大,今天分享一下我对mapreduce最后一个题目-寻找博主共同好友的解题思路

一.需求

以下是博主的好友列表数据,冒号前是一个用户,冒号后是该用户的所有好友,数据中的好友关系是单向的,共有14个博主

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的共同好友有:C, E
A和C的共同好友有:F, D

A->B	[C, E]
A->C	[F, D]
.....

二.思路分析

1.每个博主之间共有 n*(n-1) / 2 种组合方式,即14*13 / 2 = 91 种组合方式
2.使用HashMap存储每个博主及对应好友信息,博主作为 key,好友作为 value
3.使用两层for循环遍历每个博主,外层博主和内层博主进行组合,其中加以判断过滤重复的组合
4.使用ArrayList存储外层循环遍历过的博主,内层循环遍历博主时判断该博主是否存在于这个 ArrayList,如果存在则 continue

三.代码演示

说明:
1.使用KeyValueTextInputFormat作为输入格式
2.仅使用Mapper即可完成该需求

public class FindCommonFriends {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        //1.获取job对象
        Configuration conf = new Configuration();
        //设置分隔符
        conf.set(KeyValueLineRecordReader.KEY_VALUE_SEPERATOR, ":");
        Job job = Job.getInstance(conf);

        //2.设置jar路径
        job.setJarByClass(FindCommonFriends.class);

        //3.关联mapper
        job.setMapperClass(FrientMapper.class);

        //4.设置mapper输出key和value类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(Text.class);

        //5.设置最终输出的key和value类型
        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);

        //设置输入格式
        job.setInputFormatClass(KeyValueTextInputFormat.class);

        //6.设置输入输出路径
        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        //7.提交job
        boolean b = job.waitForCompletion(true);

        System.exit(b ? 0 : 1);
    }
}

class FrientMapper extends Mapper<Text, Text, Text, Text> {
    HashMap<String, String> hashMap = new HashMap<>();

    @Override
    protected void map(Text key, Text value, Context context) throws IOException, InterruptedException {
        //将key value 对存入 hashmap
        hashMap.put(key.toString(), value.toString());
    }

    @Override
    protected void cleanup(Context context) throws IOException, InterruptedException {
        System.out.println(hashMap);
        //1 遍历hashmap
        Set<Map.Entry<String, String>> entries = hashMap.entrySet();
        //2 定义一个集合,用于添加标记
        ArrayList<String> flags = new ArrayList<>();
        //第一层遍历
        for (Map.Entry<String, String> entry1 : entries) {
            //第二层遍历
            for (Map.Entry<String, String> entry2 : entries) {
                //3 判断里层 key 在外层循环中是否遍历
                if (flags.contains(entry2.getKey())) {
                    continue;
                }
                //4 判断外层 key 和里层 key 是否相同
                if (entry2.getKey().equals(entry1.getKey())) {
                    continue;
                }
                //5 定义一个集合,用于存放共同朋友
                ArrayList<String> commonFriends = new ArrayList<>();
                //获取 value 值
                String value = entry2.getValue();
                //将value分割成数组
                String[] firends = value.split(",");
                //6 循环判断这些 “朋友” 在第一层value中是否存在
                for (String friend : firends) {
                    if (entry1.getValue().contains(friend)) {
                        //7 如果存在,将该 “朋友” 存入集合
                        commonFriends.add(friend);
                    }
                }
                //8 过滤两个博主之间没有共同好友的情况
                if (!commonFriends.isEmpty()) {
                    System.out.println(entry1.getKey() + "->" + entry2.getKey() + "\t" + commonFriends);
                    context.write(new Text(entry1.getKey() + "->" + entry2.getKey()), new Text(commonFriends.toString()));
                }
            }
            flags.add(entry1.getKey());
        }
    }
}

四.运行结果

结果文件一共74行,有17行没有共同好友的记录被过滤,共计91行

A->B	[C, E]
A->C	[F, D]
A->D	[E, F]
A->E	[B, C, D]
A->F	[B, C, D, E, O]
A->G	[C, D, E, F]
A->H	[C, D, E, O]
A->I	[O]
A->J	[B, O]
A->K	[C, D]
A->L	[D, E, F]
A->M	[E, F]
B->C	[A]
B->D	[A, E]
B->E	[C]
B->F	[A, C, E]
B->G	[A, C, E]
B->H	[A, C, E]
B->I	[A]
B->K	[A, C]
B->L	[E]
B->M	[E]
B->O	[A]
C->D	[A, F]
C->E	[D]
C->F	[A, D]
C->G	[A, D, F]
C->H	[A, D]
C->I	[A]
C->K	[A, D]
C->L	[D, F]
C->M	[F]
C->O	[A, I]
D->E	[L]
D->F	[A, E]
D->G	[A, E, F]
D->H	[A, E]
D->I	[A]
D->K	[A]
D->L	[E, F]
D->M	[E, F]
D->O	[A]
E->F	[B, C, D, M]
E->G	[C, D]
E->H	[C, D]
E->J	[B]
E->K	[C, D]
E->L	[D]
F->G	[A, C, D, E]
F->H	[A, C, D, E, O]
F->I	[A, O]
F->J	[B, O]
F->K	[A, C, D]
F->L	[D, E]
F->M	[E]
F->O	[A]
G->H	[A, C, D, E]
G->I	[A]
G->K	[A, C, D]
G->L	[D, E, F]
G->M	[E, F]
G->O	[A]
H->I	[A, O]
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]
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值