00:02
客观一点啊各位。第一分后。呃,我们组就是首先想的就是这个,把这两行就是放在一块儿,A跟B嘛。然后,呃。呃,它的用冒号作为分隔,呃,冒号前面是K,后边是Y6,把它们的K放在一块,VALUE6放在一块。那Y6里如果出现,呃。有重复的就代表是共同好友。然后这个是那个。呃,Map函数首先是呃。这个setup这里面呃呃定义一个那个。然后那个。
01:00
呃,用冒号把那个K跟Y6分隔开。把那个数据放放到这个里边。然后在map函数里实现这个循环。这个。呃,循环便利就是把那个。这个A的放在一块儿,AC放在一块儿。这么循环一圈。然后生成了这个。呃,第一次,呃,生成这个输出就是这个。这个结果。然后在。Reduce reduce就把这个,呃,这里边value里边有相同的这个找出来。就是通过这个。那个两个for循环嵌套。通过寻找这个艺考的找出,然后就输出了结果。
02:04
这家同学有问题吗?有问题可以问一问,没问题就结束。可以没听懂是吧,没听懂,那大家没听,那你要再来一遍。那那就结束,那就下一周,嗯。谢谢大家,一个打分发到八委班长班上。哎,老师,呃,那个把你的这个东西打开一下,我用一下。这个还有那个。是他长得帅吗?太给面儿了。
03:00
稍等一下,我把那个项目导进去。直接看代码吧,别忘领导了。长时间没没。啊,那也行,这。哎呀。别着急啊。呃,首先我们就说拿到这个东西,我们看待需求,需求来说这个是两两之间有共同好友。何呢,肯定就是这个这个。和他的顺序没有关系,肯定是两个用户之间他有共同好友,然后他的需求还是共同好友都有谁,也就是说他们俩的共同好友,你要输出他共同好友里的所有。嗯,咱把那个这个东西粘出来吧。然后放到这里。
04:00
如果首先我我们组大概做了两种,两种思路,一第我先说第一种,第一种思路来说,呃,你拿到这批用户,首先一个用户他下面有一有一那个一个好友列表,他的好友列表和别人有没有共同的,那你怎么办呢?你肯定要和他下面的人逐一逐个对比,是否拿它里面的好友比一下,比如说I好友里面有B。艾的好友里面有B,那他在那个他和B相比吗?不用他啊对。这个这个肯定不能和B比,他和C比,直接和C比,看电力一下,这就说它下面是字符串,肯定contain。那我们要挨个逐个的去便利他的话。直接没法复制两分啊。相对来说,我认为呢,如果你要是只有这这么一份的话,我读我一行一行的读,我没法去下和下面比所有,所以呢,这个来说,我需要最好的就是我下面如果能要有一份完整的list,就是说所有的用户以及对于他对应的好友列表。
05:12
如果有这么一份,那我拿它拿上面的我一行读,读到一个用户,他用户的列表,然后拿用户去比他下面的好友,那我就能实现到他能找到他们的交集,就是说两个用户之间他的共同好友存在的一个交集,那我们就达到我们的需求了,对吧。我如何能把这一部分给他,就说这一部分所有的用户我全都放在一个list上呢?呃,我的实现是。把它我们就说map阶段,我们不可以做一个缓存嘛,在setup阶段给他就是说把那个做一个缓存数据,嗯,把所有的用户放在缓存里。看一下代码吧。
06:05
用这个打开稍微不好看。这个来说,嗯,那我我我的这个里面实现只用了一个map,只用一个map去实现它的,嗯,Map点它的setup去获取这个,我首先把这份数据全,就说这个文件放在缓存当中,把缓存的数据读出来,读到嗯,读到一个map里面,我这个map选择的是link哈,Map。我为什么没选那个哈呢?因为哈map是无序的,我要对比的时候,我。逐个嗯。找不到上个文件了。我要逐个去对比它的话。这样的话,我要是有个顺序,我我每一行读我读的呃I和下面的所有行进行去对比,它不用比它本身,当我读到第二行的时候。
07:07
就相当于说。读的第二行拿I,那就是说A用户已经便利了这个历史的所有,这个整个全区所有用户的所有,然后我拿B用户去找他和下列以下所有用户的共同用户的时候,我还要去比吗?不用了,因为我们上一层已经比过了,还要去比B吗?也不用,我只要从C开始往下读就可以了,同时C也一样,ABC上面的全都不用,当我读到B的时候,好,下一行我们开始进行对比。也就是说我这里面的实现,紧接着map,首先我们这个数据类型一看。看到哪个人数一点,二话不说,我肯定是用t value形式。然后他是用那个。号隔开嘛,所以我们直接选用k value,选用q value,我这里面设置了一个标志位,设置标志位相当于是把整个,嗯,整个我这个缓存相当于是有两份数据嘛,上面setup setup当中把这个所有数据读到这个cash user这个。
08:07
Map里面去,然后去把这个map去遍历,标志位默认是false,然后去逐个去遍历的时候,我要保证他的就说我读出这个数据的用户,也就是说这个K和你,呃,Map里面的逐行读的那个K,它俩是否相等的,相等说明它下面所有行的数据,我们要进行对比了。也就是说这个之前如果他没有,那咱下面就不用执行这个方循环结束,直接再进行下一轮的循环就OK,就是说进行下一次就可以了,然后如果它是。嗯,这个为处了的话,就是说我们上次已经找到跟他同行同级别的了,那我们就给他调这个方法,就是说获取他的相同用户,相同用户两个,这个是这个是你的,就是读的这一行的用户value流是他对应的好友列表。
09:00
这个KK就是这嗯KSK就是相当于是我读的那个,嗯,就是对需要对比的那一行,需要对比的那一行,也就是说到到我下面的来说。这个这个对比了一下,嗯,相当于是。你传过来的是?I用户的好友列表,那我对比B哈,所以对比的B的时候,B的从这个安里面去得到,就是这个map里面去得到它对应的好友列表,好友列表对比一下的长度,我肯定选择,因为我要拿前面的去遍利后面的,前面的去它转化成每一个,就是说一每一个单个单个那个字符的去和后面的那那个string进行对比嘛,Contain来对比,所以我要保证循环少数,循环次数越少,那当然效率越高了,所以我要对比一下,呃,哪一个少,哪个少我就去哪个,长度小我就不便利哪一个,所以这中间有个设置,设置之后,然后对比之后就相当于是有个content。
10:03
如果他要是包含在内,说明他两个存在一个共同的好友,共同的好友我给他就是进行一个拼接,每一个用在就他共同好友,然后再加上一个后缀进行拼接,拼接到时候相当于一个string buffer里面。判断一下,这个就相当于你整个便利便利园变了,相当于是说I和B的共同好友你已经找寻出来完了,并且与逗号隔开,那么他逗号它肯定是最后一位,它如果有好友的话,最后还有逗号。我们首先判断这个STRING8号的长度,如果长度它大于零,它才有共同好友,如果它不大于零,那我们不处理它返回到上一层,相当于是我定义的这个是最终以字符串形式来返回吗?这个如果这个有描述,下面这个操作就是去掉它最后的逗号,并转化成字符串。返回到上,返回到这个里面,然后我判断它这个字符串是否为空,如果为空,那我不做处理,如果他不为空,那那么就是两个用户进行一个拼接。
11:00
这是他对应的K,然后以安福隔开,然后再和他的共同好友以冒号隔开,然后给他写出去。写出去就OK了,然后这个对应的就是。对应的driver其实不用看了,里面设置的都是一些常规设置。这个里面无外乎加一个缓存,然后他的那个以Q的形式去读取,这种是这种方式是你找到两个用户,逐个去对比他们的共同好友,这种是一种思路,还有一种思路就是说我们第二种方案。还有一种那个就是说我们要做什么呢。某个用户就是说某,呃,某个那个好友他的。怎么说呢?这个要是描述出来,相当于是嗯。老师那个老师那个那什么。嗯,PPT啊,那那个word文档里面有那个有对应的那个方案,那个方案我们也写了一下,不过无外乎就在它里面,我给他加了两加了几个东西。
12:03
反正K的形式和combine,然后那个读起来说都一样,如果你要说具体实现,这是两种思路,我觉着反正一般不会超过这两种思路里面去的,然后你要具体实现可能会有很多种,如果这个来说,比如说这个我用的一个map来实现,你也可以再加一个reduce,那你也可以reduce里面加都可以,一种思路的实现可以有很多方案。嗯,大致是这么个。第一组俩没有,没给分的没有。
13:12
我先说一下我的思路。因为刚开始的时候,老师那个例子是用两次那个ma的过程,然后他的过程主要是用那个K大和数据的,然后看他那个写完之后,然后本来我也是想用MAP6十来聚合的,但是他写的已经非常好了,我然后就是不知道怎么来优化,然后我就想只写一个嘛。然后这些一个,但是也有很多方式嘛,然后我就写了一下我的分析过程嘛。然后刚开始想的时候,因为我们默认是那个。然后那个是TEXT1读,然后我想的方就是肯定是要一次性读一读的话,很多种方式,然后我想的是按input方,然后可比如说我可以设置它的行数很多嘛,然后一次把它读完,作为一个value,然后进行一些逻辑处理。然后或者是用缓存,然后。
14:02
然后就是说input方面它没使用,因为就是那个数是未知的嘛,虽然你可以打开档看到数,但是对来说是未知的,然后我就没用。然后我又想到了缓存,缓存我们可以在那个里面进行设置,然后设置完之后。嗯,因为我们默认默认那个map map读取还是按照那个行,每每行执行一个map方法,每行执行map方法,虽然我们可以在那个方法里面一次在缓存里面把所有的数据读出来,然后放在那个类里面,然后最终在那个clean up结束方法的时候,然后进行统一的逻辑处理,但是我觉得。就是还有那个。就是就是觉得还有很多那个IO流的操作,然后然后我我最终希望就是一次入一次输出,然后就是整个过程全部完成。然后就是等于是我在里面写了,写了类似老师那个word,他word里面两次那个video的聚焦过程。然后我的思路就是自定义了一个input,然后写了一个,然后就一次性的读取全部的文件。
15:04
然后等于是减少了,减少了那个IO6操作,然后相对于那个缓存来说就是。减减,避免了每一次那个执行慢步方法的过程。然后我就是读取,读取那个读取的过程,然后我在那个门牌里面执行的就是呃。两次那个模拟的过程,但是我那个模拟是用那个哈哈希做的,因为我们那就是利用K的那个K的来做聚合数据的。是我在里面没法弄啊,然后我能自己来一个一个方法,然后我用MAP1的,然后它的那个,然后保的一。然后就是做了两次那个哈希map的一个处理,处理完之后,然后就是便利输出,便利输出的时候我发现那个输出是无序的嘛,虽然得到了预期的结果,但是无序的,然后我就把结果Q86拼装成字符串,放在历史的集合里面进行了一次自定义的排序。然后最后排序输出,但是输出的时候,然后我又想到其他的方式,比如说默认的时候,我是按行输出的,比如说我便利list,然后进行一次逐行输出,然后或者是把list进行,呃,每每一个元素进行一个杠杠二杠N进行拼接,然后减少,等于是等于是一次写一次写出嘛,但是这样的话,我发现那个输出文件是一个帕000的,然后我想。
16:21
这个这个地方再加个优化,然后我想自己输出一个自定义的路径,然后我就用到了那个out form,当然这一步最后一步是我自己加的,其实要不要已经得到了预期的结果。然后就是写了一个那个out form还有一个,然后然后指定指定输出,输出位置是一个。然后在那个driver里面就是定,定义了我的输入,自定义的输入和输出的lay,然后就是设置到reduce的number是零。啊,下面说一下逻辑吧。逻辑还是跟就是我最初参考的,参考的方案还是老师那个word里,Word文档里面写的,但是我等于是把他的过程两个过程在里面写的思路还是跟他那个很相似的,结果输出也是很类似的,然后。
17:09
它等于是利用那个来来进行聚合排序,然后我是利用map和list进行聚合排序。啊,说下思路。首先进入进那个进入那个map task任务之后,然后等于自定义了一个file file input form,然后自义的输输入那个case text就是文件的名称,然后value是一个text,就是整个文件的全部内容。呃,然后我在reader里面写的是就是按那个buffer reader,然后一行一行的读取,读取完之后,然后我每一行每一行加一个分号,然后进进行进行区分,进行区分,这样我文件再读取到那个map map过程中,然后我利用我利用的分割,利用分割分号,然后进行。进行风暴一个list。啊,然后等于是看我的代码,就是在块类里面这个地方,然后就是分割,用方块分割,然后得到了一个list,这个list其实就是数据中的每一行,然后每一行的话,然后我进行了map处理,嗯,等于是两个map,我见了两个map,就是第一个map,就是类似老师的第一个第一个的过程,然后第二个就是第二次的过程。
18:15
的第一个map的就是供他们,供他们那个好友的friend。就是从那个图开始说吧,他这个因为现在这个图原文件的图是好友是单向的,比如说A还有BCD,然后这么多好友,B有这么多好友,然后我的我的方法。其实是借鉴老师的方法的,嗯,然后等于是把他那个。把他的好友作为可,然后找到,找到他的好友都哪些人有他的好友,然后然后再再在后面再变在再二次便利那个所有的人,然后再找到好友。嗯,说一下大码的,大码的实现吧。嗯,这个地方等于是我我都是取巧用了一些ma,然后ma处理过程,就是第一次我这抽取了一个一个ma的方法,然后里面的参数就是整,就是整个那个。
19:06
整个全部文档嘛,然后每一每一行就是A冒号,后面加他的好友,然后然后第一次我得到的等于是好一个好友,还有还有所有所有人的关系,等于是后面的所有人都有我这个人的好友。然后他的就是呃,Friend。单个friend,因为比如说当我当我以分,当我冒号截取的时候,他第一个元素就是friend,就是某个人,然后后面所有人都是他的都是的朋友,然后我得到的第一个map的就是friend,然后然后然后person就是人,然后但是但是我这个person是一个。后面做了一些处理,就是说如果这个K有的话,然后我就把那个list直接加,然后然后如果这个K没有的话,然后然后新建一个set person,然后然后把这个把这个人加进去,然后这样我得到了这个好友跟人的人的对应关系。
20:01
然后此时得到的展示就是第一次Mac。然后等于是我模拟的过程,然后第二第二次的Mac,然后就是到最终的展示效果,最终展示效果我们第一次已经得到了。就是好友跟人的关系,那我那我第二次就是得到,就是便利,后面所有的人,所有人然后得到,得到每每两个交叉的,然后他的好友。这样的话就是他的共同好友,然后我执行了第二次,第二次呢,还有卖的处理。第二次的处理,然后就是便利,首先便利,便利我上一个得到了map,然后将我的将我的那个哈set转换成一个数组,然数组之后进行了双重便利,便利完,便利的K就是person就是person就是呃。就是一个循环便利,然后然后得到每每每个人就是人跟人人加一个杠号,人然后得到他的朋友,然后这样的话呢,我我的friend还是一个,还是一个历史的,还是一个历史的形式的。啊是一个sat形式哈,Set,然后避免重复,然后同时保证了,嗯,它可以加,然后就是保证它所有的好友都可以放在一块。
21:09
然后这个方法等于我做了个抽取,因为两个逻辑完全一样。只是具体的展示不一样。这个时候我得到的结果的时候,其实已经得到了要求,但是但是它那个输出结果是没有排序的,没有排序,然后我就是。就是自定,自定义了一个类似的sort。然后用用collection,然后重启了一下那个做了一个二次排序。然后那个map,我我也没有我。不知道好不好用,然后回头再试一下,但是呃,像目前来说这个输出结果已经达到了,然后后面后面我买做完逻辑逻辑处理之后,然后我就是。就是在自定义的自定义一个out form,然后写了一个record record write里面就是完全就是自定义了一个输出路径,然后等于是一次一次读,读完一次逻辑处理,一次输出,然后输出到指定的路径,就是一个text。
22:01
可能就是好看一点吧,然后我主要是想想想加多加一点知识点加进去,然后。然后这个思路主要就是两次聚合,两次聚合的过程就是刚开始。可能很多人就是就是脑子绕不开弯。就是当你把那个逻辑理完之后,就是只要能理解两次的过程,然后后面就好写了,无论是你用缓存还是自己用一些其他的方式,都都能得到预期的结果。学校。上来了。
23:02
这样看没问题吧?然后那个咱们要做的嘛,是那个博客啊,找共同好友对吧,要做这个功能,然后之后呢,那个需求的话,前面几组我觉得已经讲的非常清楚了,然后我我就不说需求了是吧,然后之后我直奔主题,这个咱们现在呢,要做这个功能,咱们首先要想就是说要怎么样才能实现这个功能。啊,我现在第一篇啊,我写的是诶是用纯Java的方式进行处理,我觉得这样也是可以的,对吧,只不过没有大数据,但是呢,这样会带来一个问题,就是呃,首先第一它只只能一台机器对吧,一台机器进行处理,第二的话,它这块会有非常非常复杂的逻辑,所以所以我们尽量不要,呃尽量不会选这种方式。然后第二种啊是这个呃,我们可以通过这个呃,通过这个这个这个这个map reduce的方式进行获取,呃呃去处理这个东西,然后这个第一种是呃,我觉得它是偏Java的方式。然后它的核心点在于第一啊,他要这个获取这个缓存。
24:04
啊,然后这个封装B就不说了,然后第三点就是说他这个位置一定要写的是这个nonriable,然后这样的话,他在这个reduce里边才能把bin都排,就是都排到一起去。然后之后再再对这个bin里边的数据来进行处理,它与这个后边就与这个Java的方式,其实说实话本质上差不多了啊,所以这种方式我觉得我觉得也不够好。然后第三种。第三种呢,就是说这个这这个是啊咱们那个word里边的案例,然后这个这个方式呢,我觉得已经非常好了,然后这种呃这种方式呢,基本上就是呃第一步先是先是读数据对吧,然后那个呃通过这个冒号和逗号切割,然后对这个呃user和friend进行输出,然后这个在在这个呃第一次reduce的时候啊,他会他会是他是这样输出的,就是这个是好友。啊,然后这个是这个是他这个好友,他共呃就是这个是好友,然后这个是这个好友的这个用户,就拥有这个好友的用户,然后第二次再便利的时候,诶,他把这个后边的再重新组合,然后之后诶然后然后到之后再再再通过reduce,然后输出这么这么一个结果,当然这种的话呃很好很好,但是但是那个它由于它有两次的这个map。
25:23
然后所以我觉着我觉得这种的话,呃,它对这个呃,如果数据量小看不出来啊,如果数据量大的话,它会对这个磁盘的这个需求量需求会比较比较大,因为它那个IO次数比较多嘛,然后对性能会有一些有一些问题,然后所以呃我重点说一下,就是说说这个第三种。然后第三种的话,其实本质上跟跟这种的话我觉得差不多,但是那个这是这是因为是我们自己想的嘛,当时我们也我们也没看这个这个笔记,然后所以。我想说一下,说一下我们的方案,然后这个首先啊,要通过KKY6的方式啊进进行切割,然后它是对这个对这个冒号进行切割的,然后然后那个生成两个两个test嘛,一个是key,一个是value,然后再对这个value啊,通过逗号进行切割,然后生成file数组。
26:12
然后之后呢。循环输出大概是一个怎么样的情况啊,我后边有一个有一个例子大家看一下,咱们只看第一步哈,第一步的话,首先。诶,这个是我我把这个数据化简了哈,因为因为那个数据太复杂了,我把数据化简了,然后这个呃,第一步最后我们要要的是一个什么样的结果哈,就是说。通先通过冒号切,再通过逗号切,对吧,然后之后呢,像第呃,像第一第一组啊,输出的数据是这个样子的,这个这个数据是怎么来的啊,就是B跟A组合在一起。NBA,这是key。就是Y流。C跟A组合在一起,这个是K,这个是Y6,以此类推啊,就全都写好了。然后进行输出。然后。
27:01
的第二步。是要那个呃是那个呃先获取到这个KY6嘛,然后之后呢,他他现在分为呃分为这个呃有一种有一种可能性,就是说,如果他要是他有可能诶看这张图哈,他有可能就是说呃像这个用户像这个像像这个啊就是这这这一组数据,他只有一组数据。啊,就证明这个他这一组数据啊,并并没有并没有重复的好友啊,他这个他这个并没重复的好友,所以这组数据我是要排除掉的,只有有两组或者两组以上的啊。才才可以才可以这个呃,就是相当于是他有,他是有共同好友的,我才可以输出。然后之后啊,这就是所谓的呃,这种这种情况,然后还有还有一种情况就是在我在我对这个数据进行便利的时候,就是我看一下啊。在这个位置。在这个位置,他有可能,他有可能就是说你输出的时候啊,这块有可能是呃。有一个有一个CB对吧,这有可能是CA对吧,有可能是BA,这种也要排除掉。
28:02
然后之后那个把这个把这种把这种几种可能性排除掉啊,然后最后的话,他我就把这些数据。合并成了这这这这些数据,就这种数据,它是怎么合并的啊,它是这样的。呃。这是这是这是共同的好友对吧,这一步相当于是B和C有共同的好友A对吧,所以这是B-CA对吧,然后这个是。呃,A跟C有共同的好友B。ACB对吧,然后以此类推,这个也是,所以输出输出格式是输出的结果是这个样子吗。这组数据。这组数据哈,由于就是说他没他他他只有一组数据嘛,它所以他等于他就是说等于这个用户没有共同好友。然后之后那个呃,继续啊。对,大概最后最后最后最后就是就是就是呃,输出就是这个样子。然后最后就是呃,由于我已经获取到了,哎这种这种这种这这种这种形式的这个数据了,但是这种形式的数据呢,可能还存在另外一种可能性,就是第一它这个可能排序不准,A对吧,AAB对吧,这都都这就是有可能的,然后第二第二种第二种,呃第二第二个就是说那个不完美的地方是呃是有可能,你看它像这个ABC对吧。
29:19
Abe啊,也就这种情况,然后所以怎么办啊,我们要再对它进行进行一次reduce处理,哎,上边comer这个跟reduce是差不多的,但是它会比reduce更节省性能。我们。然后再进行一次reduce处理啊reduce处理。然后之后呢,他的最主要的目的就是第一排序哎。把把这个都排成AA。然后再是再是B,然后再是CDEF什么的啊,然后之后还有一个就是把这个后边的这个数据。比如前面都是AB的。然后后后边哎,合并在一起。然后,所以就引出了第三步。第三部的话。这个这个这个这个这个数据哈,就是是基本上是看不出来的,只能把顺序排一下这个。
30:02
排成这个样子,但是假设现在啊,我我我我这块又多了多了一组数据,我这又多了一个DC。是吧,当然这后边会有啊,就是大概大概看一下啊,现在先看一下这组数据,这个二。后边多多了一个DC,它会变成这个样子。它会变成这个样子,然后这个样子呢,输出输出之后会是什么样子。输出完之后前三组我看看啊,是前三组对,应该是前三组跟之前的是一样的,但是但是他又多输出了两组数据。他是哪两组?这样的啊,A跟B是一组对吧。A跟C是一组对吧?B跟C又是一组。然后现在呢,也就是说这个多了,后边的A跟C跟B跟C,然后他他们俩的共同好友都有D。然后之后。这这现在现在这样的话,就能看出这个就是说这个数据并不整齐,因为它存在着很多的这个重复,比如说A跟C是吧,A跟C对吧。
31:02
然后所以呢,我就要最后通过reduce。进行排序。然后这个最后最后排排呃呃,当然还肯定肯定这个还有一个算法,比如负循环了,然后之后那个通过Y6了,然后之后把这个把这个呃,把这个比如说A跟C的这这组数据,然后之后进行进行一个便利,然后最后拼接到后边。然后这就是呃,我们组基本上我觉着比较完美的解决方案。然后大家如果要是还有什么更好的解决方案的话,我觉得可以探讨一下。啊是这样的啊,就是那个这个这个数据的话到这块。呃,到看看啊,最后一步。对,只有最后一部输入情况,对对对对,是的是的是的,然后所以那个就说就说这事儿就要就就要请教一下是吧,就全班最帅的对吧,然后仅次于手艺超快的是吧,大海老师大海大海老师大海老师是吧,一见着八个就兴奋,然后我就可以说在这块。
32:07
稍微指点一下。
33:30
这个方案的。喂喂喂。这个题,这个题呢,其实有两种,就是两种思路。第一种思路就是大家,大家经常就是就。
34:02
一般都会想到的一种。呃,然后第二种就是老师那个。呃,Word文档上的那一种,呃。第一种呢,会。比较容易想到。呃,就是他不是有两个。这是他的AA。后面他是他的好友对吧。这边也是他的,呃。这边也是。呃,然后我们他。需要做就就就需要做一个循环去。第一次呢?第一次去。呃,他会,呃。和那个第一组和第和他自己本本身其实是不用编辑的用户,后面改了一下那个。A到那个。A到A是不用编辑的,然后他直接是A到B去一个做一个判断。
35:03
呃,AA的好友和B的好友进行去循环判断,然后第一次就是A组和其他组去判断我。只我这里只写了呃四对。四条记录。然后第二次会从B开始,然后去依次判断C和D,那个B到B也是不用判断人物。后面改了一下。然后第三次是。谁谁到D去判断。然后他每次判断他是,他会去做一个循环。去去,呃,循环。查找一下他的共同好友,然后去进行一个循环编译。查找他是否就是有没有去,有没有共同的好友,假如就看那这第二,第二排他有个C对吧,C和下面的这个C,他就是共同好友,就查找他。呃,是否有相同的?
36:01
啊,这就是。这样的一个私募,然后他又。两种解决方法。第一种呢?一个像。给他一个应对。变对象。然后去,呃。作为一个排序。排序里面呢,必须要必须要给他一个呃,这样一个判断方法,就是他有一种情况就是A和B,然后后面到了B的时候,他就有一个B到A这样一个关系嘛,所以这两种关系是一样的,所以就要把它返回一个零。就认为他们俩是相等。然后在呃阶段呢,也是缓存了一个的文件,TXT文件,把它缓存到。他不是要,然后到了阶段。到map阶段,它后面不是,呃,需要进行一个循环吗。
37:01
这个循环如果呃,他必须必须要知道这他是第几次循环,否则的话,他会他第二次的话,假如说是B。到了,他会继续循环到A。这样,呃,然后从从A开始循环。所以我们需要一个,就加了一个计数器。所以我就加了一个计数器来来判断它来技术它是第几次那阶段。然后。进行,然后这就是切切割。呃,他的好友。然后。把把到了在第一个map阶段的时候,不是要设置他的好友吗,一个关系嘛。这common毕竟就是他的一个关系图。呃,设置它的A。切割出来的。对应的就是。对应的它的一个关系,然后呃,然后他的那个B。
38:00
缓存里面的。缓存里面的那个对应的那个文件。手机里面的第一条。点就是设置了它的B。然后这个循环里面呢,因为。必须要知道他的,他是第几次buff阶段,所以。所以在那个,呃,所以在这个map里面需要获取一下它的它的第几次map。所以。这里可以。从第。就从抗抗旱阶段。从低抗刺。第一次嘛。从抗呃,从第二次,从抗次去循环。去查找一下他的共同好友。就是到了第二次的话,他就是指指。查找B和C。然后到了第三次的话,他就只查找他的地。GC好,那个C就是那个面的好。就不会去返回去查找,从A开始查找了。
39:03
然后。然后也需需要把那个他们的共同好友去分割一下,通过那个逗号去分割。然后就获取了一个friends啊。那个受阻对象。然后这里就是对他的速度啊,对对这两个。去进行一个循环编辑,查找他的共同好友吗?就是下面这个。然后把公如果查询到有共同好友的话,就把它呃放到这个十人的。阶段做完之后。那就可以。就可以把他输出了。这一段这个也可以。输出这个输出完之后。呃,因为他那个有有的有的共同好友,他们是没有,有的他们是没有共同好友的,所以要把这种东这种情况排除掉,所以。
40:07
就会通过,呃。判断它的那个长度是否为零。那个value值是否为零。如果。不为零的话,他就可以输出,如果问你。你的话就不属实。这个里面就只用的到一个,没有子方法。嗯,第一种实现方法基本就是这样。然后第二种实现方法就是也是就像就是一个纯B纯Java的。的思路。呃,他呃把。把缓存文件啊。改成了一个。自定自定义的一个input。其实它那个都是都是把它缓存到,其实都是把它就是把它缓存一下。这个这个。这个自定义不是不骂这种就是。
41:01
一次性把所有文件里面的所有数据全部读取出来。相当,也就相当于是一个缓存,只不过实现方实现方式不一样,一个是自定义,一个一个是自定义,还有一个是。加缓存文件。这两个是一样是一样的,这个也可以改成那个。缓存。然后然后呃,如果存到缓存里面里面的话,那就相当于只有一次map都有。就相当于只有一次阶段。只会进入一个map。而且。而且就是在一个Mac里面去做循环。这个这第一个欠档循环就是循环就。就是第一个。他这个大循环。这样一个大循环。就是循环去判断每个呃,第一条和第二条比,然后第第一条和第三条比,这样循环比。
42:00
然后第二条就是和第三条这样一依次往下比。然后因为这个。因为它是一整个文件读取出来的嘛,所以它要进行一个切分,切分成每条数据。所以就用的那个干啥上去切分,切分成每一条数据。然后每,然后每一条数据呢,要进行去切分。呃,每条数据,因为它是一个关系,A对A对他的好友的关系嘛,用用个冒号来表示,所以他A钱,所以要成切分成。他的那个。就是people。然后他的,嗯,他的好友就是子。就是就是。这个两个循环就相当于是两个对立,对立的那种就是这两个map。这两个循环吧,就。
43:06
然后这两个都都会掉进零七。就是切成呃,然后到了内部,内部的话,这两个呃。也是建立一个空空。把它是把它把这两个建立一下关系。就这就是一个K。然后他的里面的关系呢。去他不是后面,前面不是输出了他的那个。切分成他的好友的吗?分两组,这两组他的好友去进行一个循环,循环查找。然后有相同的话,就追加到那个。死人八份,死人丢在里面。然后去设置到它的value值里面。然后还然后也需要去呃,设置部。把那个没有共同好友的那种情况去去除掉。
44:00
然后去输出这个。这里面也是用到了一个map。是一个没有没有reduce的阶段。方法,其实设计思路是一样的。
45:14
喂喂。然后就是那个一开始那个表嘛,我的思路。我的思路就是第一排,第一排就从冒号开始的第一列,第一列全部只放A,就是说最后我们把A的A的列数作为那个K值传到那个,传到下一个reduce方法里面去。就比如说把这个把这个A全部第一列只放A,然后B后面移,C后面移,就这个最后进去的,进去的那个值就是A所在的列,前面都不管,A在的列就是第一列。然后这个座位T值传到下一个reduce里面去,然后它还要封一个B,一个B就是那个前面的那个。
46:06
前面那个字母,我我是把它封装成一个line,就是一个行数,就把它那个过去的B,就是一个行数,加上这个字母就是A。所以他最后进去的话,他进同一个reduce方法里面,肯定是都是A这一列的,第二次进reduce方法肯定都是肯定都是B这一列的,所以最后那个结果就是。Switch,对,就是这个。这什么意思?就是说呃,现在我们是以A为共同好友,就是哪些人,他的好友是A,就是八第八行的第14行,第九行,就这里面是所有都具有A这个好友的这个人,所以就把这个呃,八十四九这个全部找到他之前所在行的前面的那个字母。就这张图。
47:00
根据根据这个前面的,因为我是把行数放在后面,这个便于切割,所以它找到第八行,那么这个里面的第八行肯定由A,就是123456788肯定有A。然后呃,14行也肯定有A,就所有有A的行全部出来了,然后我们再通过这个行数去找前面的冒号前面的字母,把冒号前面的字母放在那个集合里面,然后只。只需要通过一次嵌套的循环去分别得到这个字母之间的两两个组合,就比如是八跟14,八跟九,八跟七,所以我做的循环就是一次嵌套循环,第一次就从八开始,84,九一直到31,不要,然后八啊内内循环就是从呃,八后面的加一位走,就是14,八和14,八和九,八和七,八和二,最后就会换成那个相应的字母就是。比如说是那个八和14的话,就是这边的,呃,这个14应该是MM就是。
48:07
14应该是啊这一行吧,这一行ho和ho和就拼接成一个,就那个你自己定义那个形式嘛,杠杠A,然后后面就加A嘛,因为我这个A是哪个共共好友已经传过来了,就是A后面直接放A,然后直接就出来了。就下面每一行都是一样的,不过是要经过两个啊,直接就。然后最后一条,其实这个这个之前我遇到一个bug,就是这个地方,其实中间有一个N的,不过我没有注意,然后这这个地方。这个地方就出错了,然后后来我看了一下,把这个地方,因为O减去那个64的话是15,但是这个地方只有14行,所以最后我改了一下,然后最后就是这个,最后通过这个再去得到那个表的话,就应该是。就是最后的结果,其实这个结果再经过一次那个或者是reduce的话,直接就。把这个当P值嘛,P值然后去下面有相同的,比如说AB的话,BA的话,它有两个BA,一个是一和C,它它这个里面会有两对,所以把它通把它当一个值传到下一个reduce里面去,综合的话,就会把后面这个字母拼接起来,就可以得得到最后的结果。
49:20
所以就是啊,我的事情就是这样。呃,首先说一下,我叫来冲,然后呃。
50:06
好像卡了。呃,那个我先说一下这个需求,呃。首先先看这。呃,这个需求。然后以当。呃。求出那些A和B的就是A和B的共同好友或者A和C的共同好友。是可以求出的,这是第一种,这种方法可以用,比如缓存把两张表,呃。都放在内存里边,然后去做这么一个操作。呃。这是一种方法,然后第二方法就是呃,用。呃,比如那个两次。
51:04
呃,这种事就。就是两次的话是最稳定的方法。我感觉因为。我的机器它性能不太好,然后。呃。像我的一个腾讯云的还是。两核1G的对,然后。像那样比较好,因为因为后边我用一种方法,就是用的一次map,然后一次。然后加上呃一次。呃,这种方法的话。后边就会。可能是我写的不好吧,后后面有三个破循环嵌套。然后可能写的写的不太好,然后这种很消耗内存,然后想一下这个方法吧。就是第一次,第一次。我是这样想的,因为他这种,呃。和后边他们是单向的。
52:02
相当于A。A关注了后边的人,对。然后。呃。我想一下。呃,就是他们就是呃。的A相当于他们的粉丝对吧。可以这样想嘛,A相当于他们的粉丝,然后这些粉丝。比如B和C。放在一块儿。他们在那个。我们都一块儿。呃。我们都一块儿被谁关注了?牛B和C在一块儿。然后他们。怎么说呢,看看代码,看代码还是。
53:04
呃,就是。这个是第一次的结果,然后。但是我用了一个comer,然后。呃,后后边就是。呃,这些。就是我把前面前面当一个star,后边是粉丝就是。些人都关注A,关注A,关注A,然后C和B他们也关注A,这样就可以找出他们。呃,就是谁和谁都关注雷,然后这样便利这个。然就我们就可以就以得些A。
54:07
然后就用了三次的后循环。然后中间注意一点,就是比如拼接的时候最好用uffer。呃。像第一次。像第一次。结果是这个这个的结果再传到reduce里边,再做第二次。做完第二次之后就可以一次的。输入这个结果就不用两次卖了。对,那个cash的话还可以。起来方法就是把后边的。把后边的数全变成一个list,然后求这两个list的交集。
55:08
然后最后这个就是出的结果。呃,然后。对,就那样。然后,然后还有一个就是。我是在写博客,然后那个一。就是这个博客其实能能改时间什么的,然后。呃,也算机构,也算机技术,然后。可比改成2016年的之类的,然后这种就是我就是我是Java。呃,毕业之后找工作,然后上班三个月之后再来的,然后当时面试的时候就很多会要你给或者是博客之类的。
56:00
留下写一下博客什么的。好,就这谢谢大家。
57:05
喂喂。先不要喝口水。喂。呃,首先要纠正一点哈,我觉得这个题目的话可能不太合适,像那个共同好友的话,嗯,可能叫那个共同粉丝的话,他这个更契合那个题。个个他A好看那个,呃,五行E里面并没有A。
58:08
所以说我们把这个题目的话,起身那个找他们的共同粉丝更为更合体。嗯,这个是第一点要说的。然后。喂。好,我现在讲一下那个思路吧。呃,思路的话大概就是两个吧,首先第一个的话是老师那个放在那个word文档里面那个思路,还有一个的话,我想大家呃,每个组的话都应该想过一个就是把那个。所有的数据放在那个内存缓存里面,这应该是大家都能想到的。
59:00
然后他的一个思路呢,就是把首先把所有的数据啊。全部放到缓存里面,然后我们通过那个map reduce。每次读取一行数据,比如说我们第一次读取的是那个A,对吧?然后我们会拿A和那个存数据里面的每一条数据做对比,找出他们的一个共同好友。但是A和呃和子级的话,它是不能那个找共同好友的。呃,所以的话,这张图的话,就是列出了所有的一个可能的情况,就是说。需要找的话就是。黑色字体部分和那个红色字体部分,这个就是我们要求的,然后那个黑色字体和红色字体部分呢。一个是重复的,我们需要去做一下去除。呃,这个思路的话。
60:00
右边的话就是所有的数据,我们把把它放到那个内存里面。然后左边的话就是我们要读取的一个数据啊,就是我们通过map,然后进行读。我们大概来捋一下,就是比如说我们第一次map读取第一行的时候,我们读取的是AA,对吧,然后我们会拿A,呃去和内存中里面的那个BCDEF,一直到最后。呃,每一行数据做对比,找出他们的一个共同好友。呃,就相当于一次便利嘛,然后第二次,比如说我们读取第二行那个B的时候,那个时候呢,呃,这个时候我们就要做一下筛选。是浪费啊。不需要和那个A和B再进行对比了,因为B和呃,B和自己本身的话,它是没有好比的,另外的话,A之前已经和那个B已经比过了,所以B在和A进行对比的话,找共同好友的话是没有意义的,就是说我们会做一个重复的计算,就是说我们下一次遍历的时候呢,只要跟一下B。
61:05
B下面的那个C1直到最后所有的数据可以。以此类推啊,像那个C的话,我们主要做一下C和D,还有后面所有的数据做一个对比。呃,这个筛选的话,我们可以在那个程序里面设置一个开关变量就可以了。然后的话,这个就是大概的讲一下大概思路吧,这个的话就是。呃,第一个代码诶。第一个的话就是缓存文件,我把那个文件的话全部都放在那个,呃,区域里面就是一个那。全部放到内存里面吧。然后我这边所有的数据的输出呢,都是放到一个B里面的,我给它起了个名字叫common。然后那个这个病的他的一个。图斯的形式的话就是A-F,然后BCD。
62:01
呃,Eo那个BCDEO呢,就是A和F的它的一个共同好友,这个就是我们程序的最终的一个最终的一个输出结果。然后A呢,它就对应那个NAME1,然后F是对应那个NAME2,然后那个BC就是那个共同的一个好友。科病就是大概就这这个样子吧。下面看一下那个程序啊。Map程序的话还是比较简单的,首先的话。呃,第一行的话。我们就是读取一行数据嘛,对吧,但是老师那个文件的文件里面的话,它是有空行的,所以我们要做一下判断,前面两行的话就是如果它是空行,那我们就直接结束这个程序就掉了。然后的话。呃,第三行的话就是给他做一下切分。切分的第一个字段的话就是那个人的名字,然后后面的话是他的一个粉丝。
63:03
叫friends吗?呃,第四行的话。就是说我们要做一项筛选。因为我这边的话就是加了一个,就是做了一个做了一个处理啊,首先的话,我是把所有的数据都是加载到内存里面了,但是如果。呃,这个数啊,他就是那个人,我和他比较完,完了以后呢,我会把他在内存中,呃,把它做一个清空。就像这样。比如比如说我们,呃,第一次放进来的是A对吧,那。内存中是有它的数据的,他不能和自己比,所以我把他的那个value设为now。然后下面的话就是那个书法。这个开P和开value就是我们获取的一个。要对比的那个人的。他的名字,还有他的好友。
64:02
如何开启value啊?呃,不等于,那的话就是我们就可以和他做对比,这个的话就是关键逻辑,这个的话大。就是开启value,还有这个。Hot那个FIELD0这个的话我们就可以,呃,通过这种方式可以。重复计算的一个情况。就是避免了。如果A和。呃,简简单来说的话就是,如果A和B已经求过共同好友了,那我设置了这两个东西,就是说这一行还有这一行,那下次B就不会和A再再进行比较了。然后这个模块呢,就是呃,Get interception是求两个人的,他们的一个共同好友。这个这个函数呢,是在这里啊这个。把这个初级解决方案就是用一个循环嘛。两层色球啊,然后。
65:02
他便利一下,然后。呃,如果找到的话就一下,然后。最后把它变成一个。呃,然后有个情况的话,要判断一下,就是有可能两个人他是可能没有共同好友的。有共同好友,我们才给他加入到最终的一个输出结果里面。对,最后输出一下就可以了。然后因为我是那个只用一个map嘛,没有用那个reduce为如果用reduce的话,可能就是因为有那个网络IO,可能是性能会稍微差一点,但这个也是有存在一个问题,就是如果没有那个呃,Reduce的话,我们把所有的数据都放在那个Mac里面,这个对内存的要求可能会有点高。数据量比较大的话,这个可能内存可能就爆掉了。再做个对比啊。然后优化的话,我觉得,呃,好像好像。
66:03
这块的地方有没有。没有特别的多,就那个两层负循环嘛。我我想的是那个数据的话,因为应该是有Java那端提供的嘛,所以那个数据的话,我觉得应该可能他是提供过来的数据。应该是有趣的,或者说你也可以自己排下去啊,或者说和那个Java那边的话,和他们讲一下,让他们想过来的时候把那个数据排下去啊,那这样的话我们可以通过。一次循环就给它解决掉,然后那个复杂度的话就稍微降低一点。复杂度的话就是OMXMN,然后M和M就是A和B的一个集合的一个长度啊。A和B集合的最大长度啊。呃,还有一个,这是一个思路啊,就是。求呃,两个集合的交集的一个速度,还有一个的话,我想到就是呃,咱找了一下。
67:03
我找了一个不能过滤器啊。我觉得这个。感觉还是有点。有点杀鸡用牛刀啊,但是感觉这个也是挺有用的,比如说大家可以联想一下,就是说呃,现实生活中,像我们那个新浪微博嘛,一个一个大咖,他可能一个粉丝就几百万,可能这个。这个现实生活中也是存在的,对吧,但是这个数据量的话就是比较大了。这个时候呢,如果我们用双重循环的话,这个就可能就比较耗时啊,这个时候觉那个滤滤什么呢?呃,它的话就可以理解为一种空间效率很高的一个随机数据结构。呃,它的话,你可以把它理解为一个哈希函数的一个加强版啊,就是说它是通过我们哈希函数,就只有呃哈希。呃,举个简单的例子吧。
68:03
比如说那个哈希map,它不就是只有一个哈希函数嘛,那那个布隆过滤器的话,它就是有K哈希函数,它把一个元素映射成一个正列呃中的K点,然后把他们的位呃质为一呃,然后我们比较另一个K的时候,如果。它呃,用这KK,呃,K哈希函数啊对它求值,然后得出的结果和上一个K完全一样,那我们就认为他们是呃,这两个是那个呃相同的T。大概就是这个意思。以前。然后这个它它的优点呢,就是它的空间和时间效率是比较高的,这个这个我也没试过。保障都是挺好的。就是只有哈希表1/8和1/4的空间复杂度就可以了,呃,然后它存在的一个问题呢,就是。
69:01
可能就是它会存在一个文化的问题啊,就是因为。可能不同,他们的题不同,但是他们得到的结果可能是一样的。但这个问题的话,你可以通过呃选择一个呃。调整一个哈希函数的值吧。以降低它它的一个效率,呃,降低他的一个出错率的啊。这个的它的那个不容过滤器,网上代码的话是还还是比较多的,时限的话也不是特别长。那张图啊。这个大家可以去网上找一下。然后它的时间复杂度的话,大概也是和那个上一个差不多的,但是他不需要对那个,呃,对那个数字排序这个代码的话,这个这个的话我是没有写啊。然后的话就是。剩下的话就是我看了一下那个老师的例子嘛,他那呃,我觉得老师的例子还是比较好的,我就重写了一下感觉。感觉也没有什么地方可以优化,然后就把那个这边的话,我们组那个手例嘛,就是把那个呃,老师。
70:07
嘛换呃,改写成一个了啊,然后的话还唯一可以优化的地方可能就是给那个REDUCE2之前我们再给它加一个com。对那个性能稍微有点提高吧。还有,我再补充一句吧。呃,就是老师那个案例的话,就是它是和我们把那个map放到缓存里面那个思路的话,可能刚好相反,他是把那个呃。以那个粉刺为主角嘛,所以他可以,我觉得他是可以有一个优点,就是它是可以解决一个,呃。数据过于集中的问题啊,因为。一个一个人,他关注的人他可能不是特别多,可能就。最多吧,最多可能1000个就算比较多了,是吧,但一个人的粉丝的话,他是可以很多的,可以有100万个,两两百万个是吧,那我们像我前面讲的那个。
71:07
是有一个计算嘛,它这个求交集的时候,如果你把它放在一个缓存里面,那这个计算量可能是很大的,因为一和B的这个值可能就是几百万200万的。那个B的值呢,可能是很小,那如果你用老师那个例子的话,它的数据都不会太大的,一般我觉得超过1000个的话,就已经算比较多了吧,对吧。我觉得老师那个案例的话,这个这个。喂喂,你这拿了350PPT喝拿还拿了三百五的这个喝水的杯。
72:04
还是当时的讲师。是这样整去了,废了。
我来说两句