源码追踪:mapreduce中的自定义分区、默认分区和自定义分组聚合、默认分组聚合

1.自定义分区:

2.默认分区:

mapreduce中会对key进行默认hash分区,使用的是Hashpartitioner:

调用Hashpartition中的getpartition方法,里面是使用key的hashcode,

观察Text类,里面有两个字段,byte数组和数组的长度,new Text(“zzd”)时会将字符串变为byte数组,(Longwritable里面是一个long字段,将传入的值转为long类型)。

观察它的hashcode方法,调用的是父类BinaryComparable中的hashcode

Text的继承结构:

观察父类BinaryComparable中的方法:

使用的是WritableComparator中的hashBytes方法:

继而调用hashByte方法:

这就是最终计算hashcode方法:

遍历输入的key转成的字节数组,每次做运算,最终计算出hashcode值。

所以只要放到Text中的字符一样,它们转成的byte数组也一样,那么它们的hashcode一定是一样的,也就会被分到同一个区中。所以可以在map函数外Text t=new Text();,然后在map函数内对t赋值,t.set(xxx),这样避免了频繁new Text对象,hashcode是根据放的值来计算的,不像普通对象,比如你在map外new一个Student s=new Student。在map中每次s.set(xxx) 这样它们的hashcode都是相同的,因为是同一个对象,它不像Text那样是根据传入的值来计算hashcode的,所以map的输出都会被分到同一个分区去,所以如果自定义对象时如果对分区有要求一定要自己重写分区方法,如根据ip分区等。而且reduce端,要重写groupingCompator来确立分组。

分区是这样的,同理排序也是根据传入的值来做的,默认升序。

 

再来看分组:

3、自定义分组:

 

4、默认分组:

WritableComparator类:

里面的比较字段:(两两相比) 自定义的key都是要实现WritableComparable接口的。

compare方法:

先将要比较的两个key通过反序列化构建出来key1、key2,因为反序列化时要使用反射来构建对象,所以自定义

然后调用类中另一个comapre方法:

点进去,最终调用的是Comparable接口的compareTo方法:

看里面的注释:其实就是使用自定义对象的equals方法,而自定义对象Order的equals使用的是父类Object中的方法,是使用==来比较,即比较地址!所以这些对象都是不同的,也就不会被分到同一个组中,所以要自己重写分组方法,使相同订单的对象被聚合到同一组中,再传到reduce中去处理。

 

对于如Text类,比较过程为:

会调用WritableComparator的compare方法:

看一下Text中的比较方法:是根据Text中放的值转化成的字节数组来比较的,所以相同的key会被分到同一组,即传入同一个reduce处理!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值