如何在hadoop mapreduce中消除重复的文件名?

时间:2012-02-07 18:30:48

标签: hadoop

我想在hadoop mapreduce倒排索引程序的输出中消除重复的文件名。例如,输出就像 - 东西:doc1,doc1,doc1,doc2 但我希望它像 东西:doc1,doc2

2 个答案:

答案 0 :(得分:1)

您想要删除已映射的重复项,即您希望中间值列表添加到没有重复项的输出列表。我最好的办法是简单地将Iterator<Text>方法中的reduce()转换为java Set并重复更改:

while (values.hasNext()) {
    if (!first)
    toReturn.append(", ") ;
    first = false;
    toReturn.append(values.next().toString());
}

类似于:

Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
    valueSet.add(values.next());
}

for(Text value : valueSet) {
    if(!first) {
        toReturn.append(", ");
    }
    first = false;
    toReturn.append(value.toString());
}

不幸的是,我不知道将Iterator转换为Set的更好(更简洁)的方式。

这应该比橙色解决方案的时间复杂度更小,但内存消耗更高。

@Edit:有点短:

Set<Text> valueSet = new HashSet<Text>();
while (values.hasNext()) {
    Text next = values.next();
    if(!valueSet.contains(next)) {
        if(!first) {
            toReturn.append(", ");
        }
        first = false;
        toReturn.append(value.toString());
        valueSet.add(next);
    }
}

包含应该(就像添加)常量时间,所以它现在应该是O(n)。

答案 1 :(得分:0)

要使用最少量的代码更改执行此操作,只需添加一个if语句,检查您要附加的内容是否已在toReturn中:

if (!first)
    toReturn.append(", ") ;
first = false;
toReturn.append(values.next().toString());

变为

String v = values.next().toString()
if (toReturn.indexOf(v) == -1) {  // indexOf returns -1 if it is not there
    if (!first) {
        toReturn.append(", ") ;
    }
    toReturn.append(v);
    first = false
}

上面的解决方案有点慢,因为它必须每次遍历整个字符串以查看该字符串是否存在。可能最好的方法是使用HashSet收集项目,然后将HashSet中的值组合成最终的输出字符串。