mapreduce将值链接到每个键的列表中

1bqhqjot  于 2021-05-29  发布在  Hadoop
关注(0)|答案(1)|浏览(342)

我有一个小项目,我在mapreduce做,因为我是这个新的,我遇到了很多困难,所以我会感谢你的帮助。在这个项目中,我有一个包含站点和标签(每个站点有10个标签)的文件,我想通过共享标签为每个站点找到相似的站点。以3个站点为例,这是我的数据集

site1   tag1
site1   tag2
site1   tag3
site1   tag4
site1   tag5
site2   tag1
site2   tag2
site2   tag3
site2   tag11
site2   tag12
site3   tag1
site3   tag11
site3   tag13
site3   tag14
site3   tag15

(在这个例子中,我为每个站点只做了5个)。我要做的是做一个mapreduce,它的键是站点的标签和值。我想让每个标记都得到一个包含此标记的站点列表(或数组或其他什么),因此在本例中:

tag1: site1, site2, site3
tag2: site1,site2
tag3: site1, site2
tag4: site1

以此类推,然后遍历列表,对于每一个公共对,在它旁边给出一个值1,如下所示

tag1: site1_site2 1, site1_site3 1, site2_site3 1
tag2: site1_site2 1

以此类推,然后链接另一个mapreduce作业,对我为其编写的代码中的每一对的值求和

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

    private Text site = new Text();
    private Text tag = new Text();
    public void map(Object key, Text value, Context context) 
                       throws IOException, InterruptedException {
        StringTokenizer itr = new StringTokenizer(value.toString(), "\t");
        while (itr.hasMoreTokens()) {
            site.set(itr.nextToken());
            tag.set(itr.nextToken());
            context.write(tag, site);
        }
    }
}

public static class tagCount extends Reducer<Text,IntWritable,Text,Text> {

    public void reduce(Text key, Iterable<Text> values, Context context) 
                             throws IOException, InterruptedException {
        String res = "";
        while (values.iterator().hasNext()) {
            res = res + "," + values.iterator().next();
        }
        Text result = new Text(res);
        context.write(key, result);
    }
}

public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    Job job = Job.getInstance(conf, "tag count");
    job.setJarByClass(WordCount.class);
    job.setMapperClass(TokenizerMapper.class);
    job.setCombinerClass(tagCount.class);
    job.setReducerClass(tagCount.class);
    job.setOutputKeyClass(Text.class);
    job.setOutputValueClass(Text.class);
    FileInputFormat.addInputPath(job, new Path(args[0]));
    FileOutputFormat.setOutputPath(job, new Path(args[1]));
    System.exit(job.waitForCompletion(true) ? 0 : 1);
}

我的第一个问题是如何将reducer中的值链接在一起?从现在起我只得到一份

tag1 site1
tag1 site2

所以我试着设置一个字符串,当我迭代值向字符串添加下一个标记时,它不起作用
事先非常感谢你的帮助

slsn1g29

slsn1g291#

下面是你的减速机的重述,让你开始:

public static class TagCount extends Reducer<Text,IntWritable,Text,IntWritable> {

    private IntWritable one = new IntWritable(1);
    private Text out = new Text();

    public void reduce(Text key, Iterable<Text> values, Context context) 
                         throws IOException, InterruptedException {

        List<String> sites = new ArrayList<String>();
        for (Text t : values) {
            sites.add(t.toString());
        }

        for (int i=0; i<sites.size()-1; i++) {
            for (int j=i+1; j<sites.size(); j++) {
                out.set(sites.get(i) + "_" + sites.get(j))
                context.write(out, one);
            }
        }
    }
}

总结:
您需要构建一个值的内部集合。在本例中,我使用了字符串列表,这是最安全的方法,直到您熟悉hadoop如何重用对象为止。
此代码假定 sites 不会太大,所以一个改进是在它的大小周围添加一些检查,因为我们将它放在内存中,下面的context.write将扩展数据。
然后遍历站点并生成排列,写出每个排列。
把数据写出来 SequenceFileOutputFormat 然后你接下来的工作 SequenceFileInputFormat 输入Map器的类型将是 Text 以及 IntWritable .

相关问题