【问题标题】:Java Hadoop wierd join behaviourJava Hadoop 奇怪的连接行为
【发布时间】:2021-01-03 10:42:35
【问题描述】:

目标

我有两个 csv 文件试图在它们之间建立连接。一个包含movieId、title,另一个包含userId、movieId、comment-tag。我想通过打印标题comment_count 找出每部电影有多少个cmets-tags。所以我的代码:

驱动程序

public class Driver
{
    public Driver(String[] args)
    {
        if (args.length < 3) {
            System.err.println("input path ");
        }

        try {
            Job job = Job.getInstance();
            job.setJobName("movie tag count");

            // set file input/output path
            MultipleInputs.addInputPath(job, new Path(args[1]), TextInputFormat.class, TagMapper.class);
            MultipleInputs.addInputPath(job, new Path(args[2]), TextInputFormat.class, MovieMapper.class);
            FileOutputFormat.setOutputPath(job, new Path(args[3]));

            // set jar class name
            job.setJarByClass(Driver.class);

            // set mapper and reducer to job
            job.setReducerClass(Reducer.class);

            // set output key class
            job.setOutputKeyClass(Text.class);
            job.setOutputValueClass(Text.class);

            int returnValue = job.waitForCompletion(true) ? 0 : 1;

            System.out.println(job.isSuccessful());
            System.exit(returnValue);
        } catch (IOException | ClassNotFoundException | InterruptedException e) {
            e.printStackTrace();
        }
    }
}

电影映射器

public class MovieMapper extends org.apache.hadoop.mapreduce.Mapper<Object, Text, Text, Text>
{
    @Override
    protected void map(Object key, Text value, Context context) throws IOException, InterruptedException
    {
        String line = value.toString();
        String[] items = line.split("(?!\\B\"[^\"]*),(?![^\"]*\"\\B)"); //comma not in quotes

        String movieId = items[0].trim();
        if(tryParseInt(movieId))
        {
            context.write(new Text(movieId), new Text(items[1].trim()));
        }
    }

    private boolean tryParseInt(String s)
    {
        try {
            Integer.parseInt(s);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
}

标签映射器

public class TagMapper extends org.apache.hadoop.mapreduce.Mapper<Object, Text, Text, Text>
{
    @Override
    protected void map(Object key, Text value, Context context) throws IOException, InterruptedException
    {
        String line = value.toString();
        String[] items = line.split("(?!\\B\"[^\"]*),(?![^\"]*\"\\B)");

        String movieId = items[1].trim();
        if(tryParseInt(movieId))
        {
            context.write(new Text(movieId), new Text("_"));
        }
    }

    private boolean tryParseInt(String s)
    {
        try {
            Integer.parseInt(s);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
}

减速器

public class Reducer extends org.apache.hadoop.mapreduce.Reducer<Text, Text, Text, IntWritable>
{
    @Override
    protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException
    {
        int noOfFrequency = 0;
        Text movieTitle = new Text();
        for (Text o : values)
        {
            if(o.toString().trim().equals("_"))
            {
                noOfFrequency++;
            }
            else
            {
                System.out.println(o.toString());
                movieTitle = o;
            }
        }
        context.write(movieTitle, new IntWritable(noOfFrequency));
    }
}

问题

我得到的结果是这样的:

标题,计数

_,计数

标题,计数

标题,计数

_,计数

标题,计数

_,计数

这个 _ 如何成为关键?我无法理解。有一个 if 语句检查是否有 _ 计数,不要将其作为标题。 toString() 方法是否有问题,equals 操作失败?有什么想法吗?

【问题讨论】:

    标签: java hadoop mapreduce


    【解决方案1】:

    这并不奇怪,因为您遍历valueso 是指向values 元素的指针,这里是Text。在某个时间点,您将movieTitle 指向o 指向movieTitle = o 的位置。在接下来的迭代中,o 指向 "_"movieTitle 也指向 "_"

    如果您像这样更改代码,一切正常:

    int noOfFrequency = 0;                                    
     Text movieTitle = null;                                  
    for (Text o : values)                                     
    {                                                         
        if(o.toString().trim().equals("_"))                   
        {                                                     
            noOfFrequency++;                                  
        }                                                     
        else                                                  
        {                                                     
            movieTitle = new Text(o.toString());              
        }                                                     
    }                                                         
    context.write(movieTitle, new IntWritable(noOfFrequency));
                                                          
    

    【讨论】:

    • 非常感谢!这很明显..我应该想到这一点,但我认为 hadoop 处理线程的方式有问题。
    猜你喜欢
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多