【问题标题】:How can I split words by the second tab for MapReduce?如何按 MapReduce 的第二个选项卡拆分单词?
【发布时间】:2015-03-02 23:50:18
【问题描述】:

我正在对一些网络数据进行 MapReduces。 (我是 MapReduce 新手,所以想想经典的 WordCount 类型的东西。)输入文件如下,数字后跟一个制表符:

3 2 2 4 2 2 2 3 3

虽然我了解如何获得数字的经典“字数”,但我真正想做的是成对评估数字,因此映射器会将上述内容读取为 '3 2', '2 2 '、'2 4'、'2 2' 等等。我该怎么做呢?我想所有必要的就是调整 StringTokenizer 以按第二个选项卡或其他东西拆分单词,但我该怎么做呢?这甚至可能吗?

这是我正在使用的 Java 代码,到目前为止,它只是 MapReduce 中的经典 WordCount 示例:

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

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

public void map(Object key, Text value, Context context
                ) throws IOException, InterruptedException {
  StringTokenizer itr = new StringTokenizer(value.toString());
  while (itr.hasMoreTokens()) {
    word.set(itr.nextToken());
    context.write(word, one);
  }
}
}

【问题讨论】:

    标签: java string hadoop mapreduce


    【解决方案1】:

    您可以轻松地修改 WordCount 以获得您的预期行为。

    public static class TokenizerMapper 
       extends Mapper<Object, Text, Text, IntWritable>{
    
    private final static IntWritable one = new IntWritable(1);
    private Text word = new Text();
    
    public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
      StringTokenizer itr = new StringTokenizer(value.toString());
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        String myString = word.toString();
        String [] numbers = myString.split("\t"); // split by tab
        if (numbers.length> 2)
        {
            // you need at least two numbers to make one pair
            int first = Integer.parseInt(numbers[0]);
            int second;
            for (int i=1; i < numbers.length; ++i)
            {
               second = Integer.parseInt(numbers[i]);
               Text keynew = new Text(first+"\t"+second);
               context.write(keynew, one);
               // your second will be the first in the next loop iteration
               first = second;
            }
        }
      }
    }
    }
    

    【讨论】:

    • 这看起来可行,有一些小错误,所以我更正它们然后运行它,但它实际上并没有写任何东西。知道为什么吗?
    • @user3222006 尝试将“first”和“second”变量的数据类型更改为 String 并删除 parseInt (数据中可能有一些不是数字的东西......),并确保制表符是分隔符。
    • @user3222006 顺便说一句,脚本会在输出文件夹中生成 _SUCCESS 文件吗?对吗?
    • 我不知道,不能真正访问输出文件夹,说那里什么都没有?但是,这显示了:“15/02/28 14:39:28 INFO mapreduce.Job:Job job_local619852621_0001 成功完成”,然后写入了多少字节等等。我还尝试将变量更改为不幸的是,字符串,但没有骰子。还有其他想法吗?非常感谢您迄今为止的帮助。
    • 通常,mapreduce 输出最底部的“写入字节”和“读取字节”部分让我知道“好的,所以它成功读取了文件”和“好的,它没有” t 设法写任何东西':15/02/28 14:39:28 INFO mapreduce.Job: map 100% reduce 100% 15/02/28 14:39:28 INFO mapreduce.Job: Job_local619852621_0001 成功完成... ...文件输入格式计数器读取字节数=12581691 文件输出格式计数器写入字节数=0
    【解决方案2】:

    试试这个:

    String data = "0\t0\t1\t2\t4\t5\t3\t4\t6\t7";
    String[] array = data.split("(?<=\\G\\w{1,3}\t\\w{1,3})\t");
    
        for(String s : array){
            System.out.println(s);
        }
    

    其中 {1,3} 是数字中位数的范围。

    输出:

     0  0
    
     1  2
    
     4  5
    
     3  4
    
     6  7
    

    对于您的代码,

    String[] pairsArray = value.toString().split("(?<=\\G\\w{1,3}\t\\w{1,3})\t");
    for (String pair : pairsArray) {
         context.write(new Text(pair), one);
    }
    

    【讨论】:

    • 我的意思是我理解如何在真空中拆分选项卡上的字符串,我想这里更大的问题是如何将它集成到所有 MapReduce 的类和迭代器中。就像这一切都去哪里了?
    • 您可以将它用于您的地图任务。像 value.toString().split... 这个代码 sn-p 的特别之处在于它的正则表达式,它通过您想要的第二个选项卡拆分字符串。现在您可以在代码中迭代对数组。如果您还想要其他任何东西,请告诉我。
    • 不过就是这样。 value.toString().split 无法编译,出现如下错误: WordCount.java:26: error: no suitable constructor found for StringTokenizer(String[]) StringTokenizer itr = new StringTokenizer(value.toString().split ("(?
    • 您不应该使用 StringTokenizer。我已经修改了代码。看看吧。
    • 这最终很有帮助。最终,我不得不放弃 .split(),因为我正在寻找重叠的子字符串,但意识到我没有受制于 StringTokenizer 是关键。非常感谢。
    【解决方案3】:

    感谢大家的帮助!这最终成为我想出的解决方案(在添加一些前导零以帮助格式化之后):

     public class WordCount {
    
       public static class TokenizerMapper
            extends Mapper<Object, Text, Text, IntWritable>{
    
         private final static IntWritable one = new IntWritable(1);
         private Text word = new Text();
    
         public void map(Object key, Text value, Context context
                    ) throws IOException, InterruptedException {
             String data = value.toString();
             for (int i = 0; i < (data.length() / 3) - 1; i++) {
                 String pair = data.substring(i*3, (i*3)+5);
                 context.write(new Text(pair), one);
             }
          }
       }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多