我想实现DPC算法(通过快速搜索进行聚类并找到密度峰值)。这是一项很大的工作,所以我决定从计算Rho开始。
这里是地图:
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] lineSplit = line.split(" ");
if (Double.parseDouble(lineSplit[2]) < dcThreshold) {
IntWritable one = new IntWritable(
Integer.parseInt(lineSplit[0]));
IntWritable two = new IntWritable(
Integer.parseInt(lineSplit[1]));
context.write(one, two);
}
}
这里是Reducer:
public void reduce(IntWritable key, IntWritable values, Context context)
throws IOException, InterruptedException {
int[] indexs = new int[2];
indexs[0] = Integer.parseInt(key.toString());
indexs[1] = Integer.parseInt(values.toString());
for (int i = 0; i < indexs.length; i++) {
densityCountMap.put(indexs[i],
densityCountMap.get(indexs[i]) + 1);
}
}
densityCountMap是一个哈希映射,只有在完成后才能正确。如何输出densityCountMap?以什么方式?
感谢mbaxi ,你真的鼓舞了我,因为你提到减少定义是不正确的,而且不需要densityCountMap。
我应该更明确地说,如果lineSplit [2]低于某个阈值,目标是lineSplit [0]和lineSplit [1]都会增加。实际上没有必要覆盖清理。
映射器:
public static class TokenizerMapper extends
Mapper<LongWritable, Text, IntWritable, IntWritable> {
private final static IntWritable count = new IntWritable(1);
public void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
String[] lineSplit = line.split(" ");
if (Double.parseDouble(lineSplit[2]) < dcThreshold) {
IntWritable one = new IntWritable(
Integer.parseInt(lineSplit[0]));
IntWritable two = new IntWritable(
Integer.parseInt(lineSplit[1]));
context.write(one, count);// Both should be increased
context.write(two, count);// both as key
}
}
}
减速机:
public static class IntSumReducer extends
Reducer<IntWritable, IntWritable, IntWritable, IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(IntWritable key, Iterable<IntWritable> values,
Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);//densityCountMap is redundant if having known better the structure of Map/reduce
context.write(key, result);//it equals to output densityCountMap
}
}
再次感谢,您带来的不仅仅是帮助,还有灵感。
答案 0 :(得分:3)
您可以覆盖清理(Context context)方法,继续在reduce()方法中填充densityCountMap,并在清理(Context context)方法中将内容刷新/写入磁盘。
在处理完所有行后调用cleanup()。
---按照评论部分的要求进行编辑---
如果您使用的是Eclipse编辑器,请右键单击要扩展的 Reducer 类,然后单击Source-&gt; Override / Implement Methods,否则您可以查找javadoc。
private static class RhoCalculationReducer extends Reducer<Text,Text,Text,Text> {
}
在那里您将看到以下方法列表[请注意输入参数/数据类型可能会根据您的班级定义而改变] -
cleanup(Context)
reduce(Text, Iterable<Text>, Context)
run(Context)
setup(Context)
您的reduce()或map()函数实际上是覆盖实现,您可以在其中提供自己的处理逻辑。 对于map或reduce任务,setup()和cleanup()可以分别类似于构造函数或析构函数。 在reduce任务的map开始之前调用setup(),并在任务结束时调用cleanup()。
我也看到你的缩小定义不正确,而不是&#34; IntWritable值 &#34;它应该是&#34; 可重复的值 &#34;, 对于reducer,确保单个键的值由单个reducer处理,这就是签名采用键和可迭代值列表的原因。 可能你也想要将单个键中的记录聚合在一起,并且可能不需要额外的densityCountMap,因为reducer已经负责一次性拉出给定键的所有值。