将数据放入集合都是同一个对象的引用的问题
概述
在reduce()方法中直接将形参中的key和value加入到一个集合,这样其实反复加入的其实是同一个key和value的引用,如果想要每次加入一个新的键值对对象,必须在put()前,新建一个key, 和value对象,直接表现就是输出文件的每条记录一样
举例说明
比如下面这个Reducer类,它实现的功能是将mapper传递过来的key和values中的每个元素存储到一个TreeMap中,这个TreeMap会按按key的值从大到小排序,最后在在clearup()方法中将TreeMap中所有的键值对输出到输出文件中
程序看起来没有任何问题,运行程序,查看输出文件
会发现每行记录都一样,这是为什么呢,且我在clearup()方法中将键值对写入到输出文件前打印键值对的hashCode(), 发现这些键值对的HashCode()竟然是一样的,说明他们是同一个对象,说明每次put到treeMap中的键值对都是同一个对象的引用,但是我们明明每次put的key都是不一样的呀,怎么会出现这个问题呢?
分析原因
我猜测是reduce()方法形参中的key有这样一个性质,一个Reducer内只有一个Key对象和 一个values列表对象,当我们每次调用reduce()方法,并不会新创建一个key对象, 而是会会对上一个reduce()方法中的key对象进行重用,仅仅是修改了key的值,所以虽然reduce()会被多次调用,但是每次调用reduce()方法操作的都是同一个key对象。
带着这样的猜想,回到我们的问题,发现可以解释的通了,当我们在reduce()方法中使用put(key, val)方法将键值对加入到TreeMap中,由于每次加入的key都是同一个,在TreeMap的比较器没有被重写的情况下,相同的key的键值对只会存储一个,而我定义的TreeMap是允许重复的所以这里实际上每次加入到TreeMap中的是key对象的一个新的引用。所以输出文件中的每行记录才会都是一样的。
解决方法
那么如何解决这种问题呢,那就是这reduce()方法中,在put()操作时新建一个与key等值的同类型对象,新建一个与value等值的同类型对象,用这两个新的对象做为key和value, 这样每次加入到TreeMap集合中的键值对都是一个新的键值对了,这样就行输出正确的结果了。
将reduce()方法的put()操作改成下面这样就没有问题了
运行程序,查看输出文件发现这次的输出就比较正常了,每行记录不是同一个值,且每行记录按健值从大到小排列
小白学云计算,本来就什么不会,还总是遇到别人遇不到的问题QAQ, 心里那个苦啊QAQ