Java MapReduce Hadoop StringTokenizer获取NoTouchElementException

Java MapReduce Hadoop StringTokenizer获取NoTouchElementException,java,hadoop,mapreduce,stringtokenizer,bigdata,Java,Hadoop,Mapreduce,Stringtokenizer,Bigdata,我试图使用wordcount的输出文件作为MapReduce的输入文件,该文件将显示每个计数的数量(有多少个单词出现一次、两次、三次等) 我想使用每个单词的计数作为键,1作为值,跳过单词本身 如果输入文件如下所示: 422 苹果3 水果2 大猩猩9 猴子3 斑马12 输出应为: 2.1 3.2 9.1 12.1 使用StringTokenizer分解文件,下面映射函数中的nextToken()会给出NoTouchElementException public static class Token

我试图使用wordcount的输出文件作为MapReduce的输入文件,该文件将显示每个计数的数量(有多少个单词出现一次、两次、三次等)

我想使用每个单词的计数作为键,1作为值,跳过单词本身

如果输入文件如下所示:

422
苹果3
水果2
大猩猩9
猴子3
斑马12

输出应为:

2.1
3.2
9.1
12.1

使用StringTokenizer分解文件,下面映射函数中的
nextToken()
会给出
NoTouchElementException

public static class TokenizerMapper
       extends Mapper<Object, Text, Text, IntWritable>{

    private final static IntWritable one = new IntWritable(1);
    private Text count = new Text();

    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
        StringTokenizer itr = new StringTokenizer(value.toString());
        itr.nextToken(); // Skip over first line, which has just one element
        while (itr.hasMoreTokens()) {
            itr.nextToken(); // Skip over word
            count.set(itr.nextToken()); // save count as key
            context.write(count, one);
        }
    }
}  
公共静态类TokenizerMapper
扩展映射器{
私有最终静态IntWritable one=新的IntWritable(1);
私有文本计数=新文本();
公共无效映射(对象键、文本值、上下文
)抛出IOException、InterruptedException{
StringTokenizer itr=新的StringTokenizer(value.toString());
itr.nextToken();//跳过只有一个元素的第一行
而(itr.hasMoreTokens()){
itr.nextToken();//跳过单词
count.set(itr.nextToken());//将计数另存为键
上下文。写入(计数,一);
}
}
}  

我不知道为什么或如何修复它?

欢迎使用StackOverflow joanne和MapReduce编程

我猜原因是你总是跳过第一个标记,然后要求下两个。每一行都是这样

请记住,映射在输入的不同部分并行运行,而不是按顺序运行,从第1行开始,然后到第2行。每次,StringTokenizer只为一行调用,而不是为整个输入调用。 话虽如此,您的问题的解决方案如下:

public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
    StringTokenizer itr = new StringTokenizer(value.toString()); // each time the value is a different line
    if (itr.countTokens() == 2) { //this skips the first line and other lines that possible contain one word
        itr.nextToken(); // Skip over word
        count.set(itr.nextToken()); // save count as key
        context.write(count, one);
    }
}
PS1:您也可以使用该方法,但这取决于您


<强> PS2:您还可以考虑根据您的数据和要求编写密钥为“代码> INT/EXECUTE”或“代码> WINTWREST <代码>(较慢地解析字符串作为int,但更快地传输到网络和更低的内存消耗)。p> 如果你的输入模式总是像苹果3,为什么不使用

String#split
方法来获得包含两个元素的
String[/code>元素,然后使用
elems[1]
作为计数?joanne,看看我的答案是否解决了你的问题。如果是,您可以将其标记为已接受,否则,请按照我们的建议告知我们问题是否仍然存在,或者您是否有新的错误。