我将按如下方式实现自定义元组/值类型:不使用成员变量来存储数据,而是将每个属性映射到继承Values 类型的对象列表中的固定索引。这种方法避免了常规 Bean 的“字段分组”问题。
- 不需要为字段分组添加其他属性(这很不自然)
- 避免数据重复(减少传送字节数)
- 它保留了 bean 模式的优势
字数统计示例如下:
public class WordCountTuple extends Values {
private final static long serialVersionUID = -4386109322233754497L;
// attribute indexes
/** The index of the word attribute. */
public final static int WRD_IDX = 0;
/** The index of the count attribute. */
public final static int CNT_IDX = 1;
// attribute names
/** The name of the word attribute. */
public final static String WRD_ATT = "word";
/** The name of the count attribute. */
public final static String CNT_ATT = "count";
// required for serialization
public WordCountTuple() {}
public WordCountTuple(String word, int count) {
super.add(WRD_IDX, word);
super.add(CNT_IDX, count);
}
public String getWord() {
return (String)super.get(WRD_IDX);
}
public void setWort(String word) {
super.set(WRD_IDX, word);
}
public int getCount() {
return (Integer)super.get(CNT_IDX);
}
public void setCount(int count) {
super.set(CNT_IDX, count);
}
public static Fields getSchema() {
return new Fields(WRD_ATT, CNT_ATT);
}
}
为避免不一致,“word”和“count”属性使用final static 变量。此外,方法getSchema()返回实现的模式,用于在Spout/Bolt方法.declareOutputFields(...)中声明输出流
对于输出元组,这种类型可以直接使用:
public MyOutBolt implements IRichBolt {
@Override
public void execute(Tuple tuple) {
// some more processing
String word = ...
int cnt = ...
collector.emit(new WordCountTuple(word, cnt));
}
@Override
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declare(WordCountTuple.getSchema());
}
// other methods omitted
}
对于输入元组,我建议使用以下模式:
public MyInBolt implements IRichBolt {
// use a single instance for avoid GC trashing
private final WordCountTuple input = new WordCountTuple();
@Override
public void execute(Tuple tuple) {
this.input.clear();
this.input.addAll(tuple.getValues());
String word = input.getWord();
int count = input.getCount();
// do further processing
}
// other methods omitted
}
MyOutBolt和MyInBolt可以如下连接:
TopologyBuilder b = ...
b.setBolt("out", new MyOutBolt());
b.setBolt("in", new MyInBolt()).fieldsGrouping("out", WordCountTuple.WRD_ATT);
使用字段分组很简单,因为WordCountTuple 允许单独访问每个属性。