我有一个接受包作为输入并将其转换为地图的 UDF。map 的每个键都由包中的不同元素和对应于它们的计数的值组成
但它没有通过junit测试
似乎您除了使用包含两个元组的包外,但您确实在创建一个包含具有两个字段的元组的包。
这段代码:
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
是正确的:在您的 UDF 中,您正在计算第一个字段具有相同值的元组的数量,但在测试中,您只添加了一个具有两个值的元组。
如果您想要计算与“键”具有相同值的元组的数量(其中键是元组中的第一个值),那么您所做的是正确的,但您必须更改您的测试:
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;
}
}
在这种情况下,您的测试应该通过。