我正在根据UDAF example实施UDAF。 update
阶段看起来像这样:
public void update(MutableAggregationBuffer buffer, Row input) {
if (!input.isNullAt(0)) {
String inputKey = input.getString(0);
Map<String, Long> inputValues = input.<String, Long>getJavaMap(1);
Map<String, Map<String, Long>> newData = new HashMap<>();
if (!buffer.isNullAt(0)) {
Map<String, Map<String, Long>> currData = buffer.<String, Map<String, Long>>getJavaMap(0);
newData.putAll(currData);
}
newData.put(inputKey, inputValues);
buffer.update(0, newData);
}
}
您可以看到,在每一步创建一个新的HashMap(newData),并将前一个缓冲区中的数据复制到其中。它看起来很糟糕,不得不创建新的地图并复制所有元素。所以我试过(在我的情况下,我有一个略有不同类型的地图):
bufferJavaMap = buffer.<String, Integer>getJavaMap(0);
bufferJavaMap.put("aaaa", 1);
buffer.update(0, bufferJavaMap);
我收到以下错误:
java.lang.UnsupportedOperationException
at java.util.AbstractMap.put(AbstractMap.java:209)
at dns.MergeMapUDAF.update(MergeMapUDAF.java:84)
是否可以更新现有地图?更新此地图的最佳方法是什么?
答案 0 :(得分:1)
是否可以更新现有地图?
这是不可能的,但问题比你的问题更复杂。 Spark在get
和update
上制作了完整的结构副本,因此即使删除显式副本也无法解决问题。
如果需要性能,则应避免将UserDefinedAggregateFunction
与非原子类型一起使用。