使用Java StringTokenizer拆分令牌



我有一个看起来像这样的数据集:

drawdate    lotterynumbers  meganumber  multiplier
2005-01-04  03 06 07 12 32  30            NULL
2005-01-07  02 08 14 15 51  38            NULL
etc.

和以下代码:

public class LotteryCount {
/**
* Mapper which extracts the lottery number and passes it to the Reducer with a single occurrence
*/
public static class LotteryMapper extends Mapper<Object, Text, IntWritable, IntWritable> {
private final static IntWritable one = new IntWritable(1);
private IntWritable lotteryKey;
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString(), ",");
while (itr.hasMoreTokens()) {
lotteryKey.set(Integer.valueOf(itr.nextToken()));
context.write(lotteryKey, one);
}
}
}
/**
* Reducer to sum up the occurrence
*/
public static class LotteryReducer
extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable> {
IntWritable result = new IntWritable();
public void reduce(IntWritable key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
}

它实际上是官方apache hadoop文档中的字数统计,只是根据我的数据集定制了一点。

我得到以下错误:

Caused by: java.lang.NumberFormatException: For input string: "2005-01-04"

我只对计算每个抽到的彩票号码的出现次数感兴趣。我如何使用代码中的StringTokenizer来做到这一点?我知道我必须拆分整行因为标记器是"与整体。我怎样才能把彩票号码分开,然后再数呢?

提前谢谢你

我只是对计算每个抽到的彩票号码的出现次数感兴趣。我如何使用代码中的StringTokenizer来做到这一点?我知道我必须拆分整行因为标记器是"与整体。我怎样才能把彩票号码分开,然后再数呢?

您发布的数据示例是:

drawdate    lotterynumbers  meganumber  multiplier
2005-01-04  03 06 07 12 32  30            NULL
2005-01-07  02 08 14 15 51  38            NULL

下面是一个简单的例子,还有一些注意事项:

  • 这将使用示例数据的第一行作为line,包括分隔数据字段的制表符,就像您发布的一样。
  • 它使用StringTokenizer,令牌分隔符定义为单个制表符(t)
  • 程序调用hasMoreTokens(),直到看到所有令牌,一路上打印每个令牌。
  • 输出包括左+右括号,以显示每个令牌的边界。例如,"30";有一个尾部空格字符,如果不使用[]字符就不会被注意到,与&;null &;前面的前导空格相同。
String line = "2005-01-04   03 06 07 12 32  30            NULL";
StringTokenizer tokenizer = new StringTokenizer(line, "t");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
System.out.println("token: [" + token + "]");
}

输出如下:

token: [2005-01-04 ]
token: [03 06 07 12 32 ]
token: [30 ]
token: [          NULL]

您可以采用这种方法,处理所有行,标记制表符,并使用第二个标记作为您的"lotterynumbers"数据做你喜欢的事。

第一个问题-在传递给MapReduce之前,您需要删除文件的头。

第二-你在显示的数据集中没有逗号,所以","不应该给StringTokenizer。试着用"t"代替

Next -不是所有的令牌都是整数,所以盲目调用Integer.valueOf(itr.nextToken())是行不通的。第一列是日期。您可以在循环之前调用itr.nextToken()以丢弃日期,但随后需要在末尾处理NULL

最终,映射器不需要解析任何内容。您还可以对reducer中的字符串进行计数。