0

我正在尝试简单的双元(单词对)计数,我尝试使用简单的“对”方法,现在我只是修改为尝试“条纹”方法,但是在映射器的清理例程中,不知何故我的所有键都是相同的单词对(就像最后一个单词对!)和计数。

例如文本输入是:

我的名字是富。Foo 是 Hadoop 的新手。

在映射器中,我的哈希图看起来像:

((my, name), 1), ((name, is), 1), ((is, foo), 2), ((is, new), 1), ((new, to), 1), ((to, hadoop), 1)

但是在清理例程中,我尝试打印相同的哈希图,它看起来像

((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:

地图的清理例程,在所有地图任务完成后最后执行吗?哈希是一种“全局”,它或我的迭代器有问题吗?

编辑2:

在散列之前,我必须在 map() 中的每次迭代中创建新的 TextPair Key 对象,这就是问题所在......它已解决,但想知道为什么会这样?我在 Python 中使用了 hash 很多次,它很好,没有痛苦,为什么我每次都需要创建新对象,我不明白。

4

2 回答 2

1

似乎您不是每次都创建新密钥,而是重复使用该密钥。所以你在这两种情况下得到了相同的分布,并且第一组中的最后一个键在第二组中的任何地方都使用。

于 2012-10-11T04:20:37.660 回答
0

我假设您正在使用“Hadoop:权威指南”中的 TextPair 类示例?

问题是使用可变对象作为 HashMap 的键值是不安全的。相反,您应该使用不可变键,例如原语。由于指南中的 TextPair 类示例是可变的,因此在通过键对象放置/获取/删除值时可能会出现问题。

解决此问题的一种方法是每次都创建一个新的 TextPair 对象,就像您已经做过的那样。另一种解决方法是使用 SimpleImmutableEntry 类。

我遇到了同样的问题,并通过使用 SimpleImmutableEntry 实现一个版本来解决它。

于 2013-03-27T12:52:35.210 回答