在每行的映射器中,您将创建两个键,一个用于 col1,另一个用于 col2,其中值从每列计数,如下所示:
2,1 -> 2:{1, 0} 和 1:{0, 1}
2,3 -> 2:{1, 0} 和 3:{0, 1}
1,2 -> 1:{1, 0} 和 2:{0, 1}
3,1 -> 3:{1, 0} 和 1:{0, 1}
4,2 -> 4:{1, 0} 和 2:{0, 1}
然后在 reducer 中,您将获得这些结果,其中每一行是每个 reduce 调用的键和值组合:
1 -> {0, 1}, {1, 0}, {0, 1}(添加它们将产生 -1)
2 -> {1, 0}, 2:{1, 0}, 2:{0, 1}, 2:{0, 1}(相加将产生 0)
3 -> {0, 1}, {1, 0}(添加它们将产生 0)
4 -> {1, 0}(添加它们将产生 1)
更新:
这是 Hadoop 示例(它未经测试,可能需要一些调整才能使其正常工作):
public class TheMapper extends Mapper<LongWritable, Text, Text, ArrayPrimitiveWritable>{
protected void map(LongWritable offset, Text value, Context context)
throws IOException, InterruptedException {
StringTokenizer tok = new StringTokenizer( value.toString(), "," );
Text col1 = new Text( tok.nextToken() );
context.write( col1, toArray(1, 0) );
Text col2 = new Text( tok.nextToken() );
context.write( col2, toArray(0, 1) );
}
private ArrayPrimitiveWritable toArray(int v1, int v2){
return new ArrayPrimitiveWritable( new int[]{i1, i2} );
}
}
public class TheReducer extends Reducer<Text, ArrayPrimitiveWritable, Text, Text> {
public void reduce(Text key, Iterable<ArrayPrimitiveWritable> values, Context context)
throws IOException, InterruptedException {
Iterator<ArrayPrimitiveWritable> i = values.iterator();
int count = 0;
while ( i.hasNext() ){
int[] counts = (int[])i.next().get();
count += counts[0];
count -= counts[1];
}
context.write( key, new Text("" + count) );
}
}