我有一个UDF接受一个包作为输入并将其转换为地图。地图的每个键都包含在包中的不同元素以及与其计数相对应的值
但它没有通过junit测试
答案 0 :(得分:0)
除了使用一包两个元组之外,你似乎还在创建一个包含两个字段的元组的包。
此代码:
DataBag dataBag = bagFactory.newDefaultBag();
Tuple nestedTuple = tupleFactory.newTuple(2);
nestedTuple.set(0, "12345");
nestedTuple.set(1, "12345");
dataBag.add(nestedTuple);
应转换为:
DataBag dataBag = bagFactory.newDefaultBag();
Tuple tupleA = tupleFactory.newTuple(1);
tupleA.set(0, "12345");
dataBag.add(tupleA);
Tuple tupleB = tupleFactory.newTuple(1);
tupleB.set(0, "12345");
dataBag.add(tupleB);
或者你可以迭代你所有的元组字段。
答案 1 :(得分:0)
1
的输出是正确的:在您的UDF中,您计算的是第一个字段具有相同值的元组数,但在测试中,您只添加一个具有两个值的元组。
如果你想要的是计算与"键"相同值的元组数。 (其中key是元组中的第一个值),那么你所做的是正确的,但你必须改变你的测试:
public void testExecWithSimpleMap() throws Exception {
Tuple inputTuple = tupleFactory.newTuple(1);
DataBag dataBag = bagFactory.newDefaultBag();
Tuple nestedTuple = tupleFactory.newTuple(2);
nestedTuple.set(0, "12345");
nestedTuple.set(1, "another value");
dataBag.add(nestedTuple);
// Add a second tuple
nestedTuple.set(0, "12345");
nestedTuple.set(1, "and another value");
dataBag.add(nestedTuple);
inputTuple.set(0,dataBag);
Map output = testClass.exec(inputTuple);
assertEquals(output.size(), 1);
System.out.println(output.get("12345"));
assertEquals(output.get("12345"),2);
}
然而,如果你想要的是计算整个Bag中重复值的次数,无论它是在不同的元组上还是在同一个元组中,(在你的问题中不是很清楚),那么你需要改变你的UDF:
public class BagToMap extends EvalFunc<Map> {
public Map exec(Tuple input) throws IOException {
if(input == null) {
return null;
}
DataBag values = (DataBag)input.get(0);
Map<String, Integer> m = new HashMap<String, Integer>();
for (Iterator<Tuple> it = values.iterator(); it.hasNext();) {
Tuple t = it.next();
// Iterate through the Tuple as well
for (Iterator<Object> it2 = t.iterator(); it2.hasNext();) {
Object o = it2.next();
String key = o.toString();
if(m.containsKey(key)) {
m.put(key, m.get(key)+1);
} else {
m.put(key, 1);
}
}
}
return m;
}
}
在这种情况下,您的测试应该通过。