我想在hadoop mapreduce倒排索引程序的输出中消除重复的文件名。例如,输出就像 - 东西:doc1,doc1,doc1,doc2 但我希望它像 东西:doc1,doc2
答案 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
中的值组合成最终的输出字符串。