MapReduce中Reduce阶段的对象重用以及Map阶段的空行表现

Hadoop中迭代器的对象重用

在书写MapReduce程序的时候,我们会自定义实现一个Reduce类,其中需要重写reduce函数,而reduce函数的格式如下(类型使用Text进行举例):

1
protected void reduce(Text key, Iterable<Text> values, Reducer<Text, Text, Text, Text>.Context context)

可以看到values的类型是一个迭代器,使用增强for可以进行迭代。但是在实际过程中,每次迭代其实是对当前的对象进行一次重新的赋值,也就是说在整个过程中,堆空间中只有一个对象的空间。举例来说,对于如下的代码,我们想实现的功能是将每个value都加入到list列表当中:

1
2
3
4
ArrayList<Text> list = new ArrayList<>();
for (Text value : values) {
list.add(value);
}

假设values中的值为["1", "2", "3"],实际执行这个代码之后,会发现list中的值是["3", "3", "3"]。这是因为每次add的实际上是同一个对象引用,而在迭代过程中每次会对这个对象重新赋值。最后一次迭代将对象赋值为3,而list中每个元素其实都是指向了同一个对象,因此list中的值全部为3。

为了解决这个问题,需要在每次迭代的时候重新new一个对象,然后将value的值赋值给这个对象,这样就可以保证每次迭代得到不同的对象引用。

Map阶段的空行表现

第二个问题是探究Map阶段的空行表现。

首先需要考虑\n\r这两个字符:

  • \n:ASCII = 10,表示换行
  • \r:ASCII = 13,表示回车,将光标移动到本行行首

在不同的操作系统上,enter键的表现也有所不同:

  • 在Linux系统中,敲入enter键,在文件中会输入\n
  • 在Windows系统中,敲入enter键,在文件中会输入\r\n
  • 在Mac系统中,敲入enter键,在文件中会输入\n

并且不同的编辑软件对于行数的显示方式也有所不同,在Vim中,文件中有多少个\n,就认为文件有多少行。而在Windows的编辑器中,一般显示的行数会比实际的\n数目要更多。

在MapReduce程序中,默认输入的键值对类型是<LongWritable, Text>,表示文件偏移量以及一行的内容。默认按照\n\r或者\r\n进行切分。

可以在程序中指定自定义的行终止符,参数为textinputformat.record.delimiter

假如MapReduce读入一行空行,即只有终止符,那么这一行也会被读入进来,并且读入的是空字符串,内容为空,长度为0。


MapReduce中Reduce阶段的对象重用以及Map阶段的空行表现
http://example.com/2022/04/26/MapReduce中Reduce阶段的对象重用以及Map阶段的空行表现/
作者
EverNorif
发布于
2022年4月26日
许可协议