Q:

MapReduce: Group results of Reducer into chunks of fixed size

I am using Map Reduce framework.
Let's say this is the input list [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P ,Q, R, S, T, U, V, W, X, Y, Z]
 and my Mapper produces the following output:
<"Key 1" : A>
<"Key 2" : B>
<"Key 3" : C>
<"Key 1" : D>
<"Key 2" : E>
<"Key 3" : F>
<"Key 1" : G>
<"Key 2" : H>
<"Key 3" : I>
<"Key 1" : J>
<"Key 2" : K>
<"Key 3" : L>
<"Key 1" : M>
<"Key 2" : N>
<"Key 3" : O>
<"Key 1" : P>
<"Key 2" : Q>
<"Key 3" : R>
<"Key 1" : S>
<"Key 2" : T>
<"Key 3" : U>
<"Key 1" : V>
<"Key 2" : W>
<"Key 3" : X>
<"Key 1" : Y>
<"Key 2" : Z>

Now the Reducer output will normally be something like this:
<"Key 1" : A, D, G, J, M, P, S, V, Y>
<"Key 2" : B, E, H, K, N, Q, T, W, Z>
<"Key 3" : C, F, I, L, O, R, U, X>

But what I want to do is something like this: 
I want to club the output for each key into chunks of 3 and then produce the final Reducer output.
So I want my Reducer output to look something like this:
<"Key 1" : [A, D, G], [J, M, P], [S, V, Y]>
<"Key 2" : [B, E, H], [K, N, Q], [T, W, Z]>
<"Key 3" : [C, F, I], [L, O, R], [U, X]>

Any help will be greatly appreciated since I am stuck on this issue since two days. I am not able to figure out the last part i.e. how to group the output into chunks of 3.
P.S. If the chunk size is less than 3 (like in the example for the last key) then it's fine but it should not exceed 3.

A:

I think, it is simple to do:

In your reducer, just take 3 values at a time into a for loop.
Concatenate these three with a delimiter of your choice and write to context
context.write(Key, Value)

Please note that you can write to context as many time you wish, i.e.
  for each chunk of 3 output simply write to context and then take next
  set of 3 values.

Please let me know if you find any difficulty.
A more sophisticated solution could be using MultiOutputs. You can even write to different files using this. 
A very good example is here using hadoop 1.0.2
Below is the example taken from javadocs:
Usage in Reducer:

 <K, V> String generateFileName(K k, V v) {
   return k.toString() + "_" + v.toString();
 }

 public class MOReduce extends
   Reducer<WritableComparable, Writable,WritableComparable, Writable> {
 private MultipleOutputs mos;
 public void setup(Context context) {
 ...
 mos = new MultipleOutputs(context);
 }

 public void reduce(WritableComparable key, Iterator<Writable> values,
 Context context)
 throws IOException {
 ...
 mos.write("text", , key, new Text("Hello"));
 mos.write("seq", LongWritable(1), new Text("Bye"), "seq_a");
 mos.write("seq", LongWritable(2), key, new Text("Chau"), "seq_b");
 mos.write(key, new Text("value"), generateFileName(key, new Text("value")));
 ...
 }

 public void cleanup(Context) throws IOException {
 mos.close();
 ...
 }

 }

