WordCount - надём слово которое встречается максимальное число раз

Добавим в public static class IntSumReducer два дополнительных поля для хранения слова которое входит в текст максимум раз и числа вхождений:

Text max_occured_key = new Text();
int max_sum = 0;

И также переопределим родительский метод, который вызывается после того как редуктор отработал:

	
        @Override
	protected void cleanup(Context context)  throws InterruptedException {
	  try{
	context.write(new Text("maximum=====  "), new IntWritable(0)); // для разделения
	context.write(max_occured_key, new IntWritable(max_sum)); // максимум (сам ответ)
	context.write(new Text("-------------- "), new IntWritable(0)); // для разделения
	} 
	catch(IOException e){
		  e.printStackTrace();
		}
     }

а вот Job сконфигурируем таким образом:

    Job job = new Job(conf, "word count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
   // job.setCombinerClass(IntSumReducer.class);
    job.setReducerClass(IntSumReducer.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(IntWritable.class);
    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));

"Выходной файл" программы будет выглядеть как-то так.

То есть в общем-то всё осталось по-прежнему, но мы убрали локальный редуктор, в качестве которого предлагалось использовать наш основной редуктор - IntSumReducer.class, кстати - если строчку раскомментировать, то мы получим вот такой вывод - то есть локальный редуктор будет запущен (создан) дважды (у нас два файла) - но его работа никак не повлияет на окончательный вывод главного редуктора.

Ещё

Кстати, ещё можно посмотреть когда запускается редуктор, а когда комбинаторы (если строчку раскомментировать) -
чтобы напечатать "относительный момент запуска" -переопределим метод редуктора setup() (вызывается до начала остальных действий редуктора - в начале подзадачи):

@Override
	protected void setup(Context context) throws IOException,
                     InterruptedException{
		try{
		   context.write(new Text("reduser start "), new IntWritable(0));
		} 
		catch(IOException e){
			  e.printStackTrace();
		}
	}

Тогда мы получим вот такой вывод.

Отдельный комбинатор

Теперь неплохо было бы выделить комбинатор в отдельный класс - дабы убедиться что это именно комбинатор начинается с данной строки (в файле вывода, так как например здесь не понятно - точно ли первая строка относится к редуктору или же к комбинатору)

Так как в примере выше мы видели, что можно использовать класс типа "редуктор" для комбинатора -поэтому просто скопируем наш IntSumReducer , переименуем его в IntSumCombiner - и поменяем комментарии для выводимых (выходных) данных.

Теперь видно, что редуктор в нашем случае действительно запускается раньше комбинеров, но результат возвращает уже после них.