package com.github.elazarl.multireducers; import com.google.common.collect.Lists; import org.apache.hadoop.mapreduce.lib.reduce.WrappedReducer; import java.io.IOException; import java.util.List; /** * MultiCombiner would run the defined combiner for each mapper. If no combiner is defined * for this particular class - it'll simply forward the values. * If no mapper have any combiner defined - no combiner would run for the job. */ public class MultiCombiner extends MultiReducer<PerMapperOutputKey, PerMapperOutputValue> { public static final String CONF_KEY = "com.github.elazarl.multireducers.combiners"; @Override protected String conf_key() { return CONF_KEY; } @SuppressWarnings("unchecked") @Override protected void setup(Context context) throws IOException, InterruptedException { int n = context.getConfiguration().getStrings(conf_key()).length; WrappedReducer wrappedReducer = new WrappedReducer(); for (int i = 0; i < n; i++) { final int finalI = i; contexts.add(wrappedReducer.new Context(context) { @Override public void write(Object key, Object value) throws IOException, InterruptedException { super.write(new PerMapperOutputKey(finalI, key), new PerMapperOutputValue(finalI, value)); } }); } super.setup(context); } @Override protected Context getContextForReducer(Context context, int i) { return contexts.get(i); } private List<Context> contexts = Lists.newArrayList(); }