我正在尝试简单的双格(词对)计数,我尝试了简单的“对”方法,现在我只是修改了尝试“条纹”方法,但在mapper的清理例程中,不知何故我的所有键都是相同的词对(就像在最后一个词对中一样!)而且很重要。
e、 g.文本输入为:
我叫福。foo是hadoop的新成员。
在mapper中,我的hashmap看起来像:
((my, name), 1), ((name, is), 1), ((is, foo), 2), ((is, new), 1), ((new, to), 1), ((to, hadoop), 1)
但在清理例程中,我尝试打印相同的hashmap,看起来像
((to, hadoop), 1), ((to, hadoop), 1), ((to, hadoop), 2), ((to, hadoop), 1), ((to, hadoop), 1), ((to, hadoop), 1)
我的代码看起来像:
Map Class:
private HashMap<TextPair, Integer> h = new HashMap<TextPair, Integer>();;
void map(...) :
...
StringTokenizer itr = new StringTokenizer(value.toString());
left = itr.nextToken();
while(itr.hasMoreTokens()) {
right = itr.nextToken();
if(left != null && right!= null) {
**//I have to create new TextPair(key object) each time!**
key.set(new Text(left.toLowerCase()), new Text(right.toLowerCase()));
//If key is there, just do count + 1 else add key with value 1
if(h.containsKey(key)) {
int total = h.get(key) + 1;
h.put(key, total);
} else {
System.out.println("key: "+ key.toString()+ " => 1");
h.put(key, 1);
}
//context.write(key, one);
}
left = right;
}
....
void cleanup(...):
Iterator<Entry<TextPair, Integer>> itr = h.entrySet().iterator();
while(itr.hasNext()) {
Entry<TextPair, Integer> entry = itr.next();
TextPair key = entry.getKey();
int total = entry.getValue().intValue();
System.out.println("--- MAP CLEANUP ---: key: "+ key.toString() + " => Total: "+ total);
context.write(key, new IntWritable(total));
}
...
注意:textpair是我的自定义密钥类。有什么建议吗?
编辑1:
所有Map任务完成后,是否执行Map的清理例程?hash是一种“全局”的,它或者我的迭代器有什么问题吗?
编辑2:
在散列之前,我必须在map()的每次迭代中创建新的textpair key对象,这就是问题所在。。它解决了,但不知道为什么会这样?我用python做了很多次hash,很好,没有痛苦,为什么每次都要创建新的对象,我不明白。
2条答案
按热度按时间2w3kk1z51#
我假设您使用的是“hadoop:the definalite guide”中的textpair类示例?
问题是使用可变对象作为hashmap的键值是不安全的。相反,应该使用不可变键,如原语。由于指南中的textpair类示例是可变的,因此在通过键对象放置/获取/移除值时可能会出现问题。
解决这个问题的一种方法是每次都创建一个新的textpair对象,就像您已经做的那样。另一种解决方法是使用simpleimutableentry类。
我遇到了与您相同的问题,并通过使用simpleimutableentry实现一个版本来解决它。
llycmphe2#
似乎不是每次都创建新密钥,而是重用一个。所以这两种情况下的分布都是一样的,第一组中的最后一个键在第二组中的任何地方都被使用。