JavaHadoop:如何创建映射器,将其作为输入文件并给出输出,即每个文件中的行数?

JavaHadoop:如何创建映射器,将其作为输入文件并给出输出,即每个文件中的行数?,java,hadoop,mapreduce,distributed,Java,Hadoop,Mapreduce,Distributed,我是Hadoop新手,我只运行了wordCount示例: 假设我们有一个包含3个文件的文件夹。我希望每个文件都有一个映射器,这个映射器将只计算行数并将其返回到reducer 然后,reducer将从每个映射器获取行数作为输入,并将所有3个文件中存在的行总数作为输出 因此,如果我们有以下3个文件 input1.txt input2.txt input3.txt 地图绘制者返回: mapper1 -> [input1.txt, 3] mapper2 -> [input2.txt, 4]

我是Hadoop新手,我只运行了wordCount示例:

假设我们有一个包含3个文件的文件夹。我希望每个文件都有一个映射器,这个映射器将只计算行数并将其返回到reducer

然后,reducer将从每个映射器获取行数作为输入,并将所有3个文件中存在的行总数作为输出

因此,如果我们有以下3个文件

input1.txt
input2.txt
input3.txt
地图绘制者返回:

mapper1 -> [input1.txt, 3]
mapper2 -> [input2.txt, 4]
mapper3 -> [input3.txt, 9]
减速器的输出为

3+4+9 = 16 
我已经在一个简单的java应用程序中完成了这项工作,所以我想在Hadoop中完成这项工作。我只有一台计算机,想尝试在伪分布式环境下运行

我怎样才能做到这一点?我应该采取什么适当的步骤

我的代码应该像apache示例中的那样吗?我将有两个静态类,一个用于mapper,一个用于reducer?或者我应该有3个类,每个映射器一个

如果你能指导我,我不知道如何做到这一点,我相信如果我能写一些代码来做这些事情,那么我将能够在未来编写更复杂的应用程序


谢谢

我注意到您使用了0.18版本的文档。(最新)

第一个建议-使用IDE(eclipse、IDEA等)。这真的有助于填补空白

在实际的HDFS中,您无法知道文件的每一部分位于何处(不同的机器和集群)。无法保证X行甚至会与Y行驻留在同一磁盘上。也无法保证X行不会在不同的机器上拆分(HDF以块的形式分发数据,通常每个块64Mb)这意味着您不能假设同一个映射程序将处理整个文件。您可以确保的是,每个文件都由同一个reducer处理

由于从映射器发送的每个键的reducer都是唯一的,因此我将使用文件名作为映射器中的输出键。此外,映射器的默认输入类是
TextInputFormat
,这意味着每个映射器将单独接收一整行(由LF或CR终止)。然后,您可以从映射器发出文件名和数字1(或其他与计算无关的内容)。然后,在reducer中,您只需使用一个循环来计算文件名的接收次数:

在映射器的映射函数中 如果只想计算所有文件中的总行数,只需在所有映射器中发出相同的键(而不是文件名)。这样,只有一个减速机来处理所有行计数:

// no need for filename
context.write( new Text("blah"), new Text("1") );
您还可以链接一个作业,该作业将处理每个文件的行数输出,或者执行其他有趣的操作—这取决于您

我留下了一些样板代码,但基本的都在那里。一定要检查我,因为我大部分都是凭记忆输入的:)


希望这有帮助

除了sa125的答案之外,您还可以通过不为每个输入记录发送记录,而只是在映射器中累积一个计数器,然后在映射器清理方法中,发送文件名和计数值来极大地提高性能:

public class LineMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
    protected long lines = 0;

    @Override
    protected void cleanup(Context context) throws IOException,
            InterruptedException {
        FileSplit split = (FileSplit) context.getInputSplit();
        String filename = split.getPath().toString();

        context.write(new Text(filename), new LongWritable(lines));
    }

    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        lines++;
    }
}
公共类LineMapper扩展映射器{
受保护的长线=0;
@凌驾
受保护的空洞清理(上下文上下文)引发IOException,
中断异常{
FileSplit split=(FileSplit)context.getInputSplit();
字符串文件名=split.getPath().toString();
write(新文本(文件名),新长可写(行));
}
@凌驾
受保护的void映射(可长写键、文本值、上下文)
抛出IOException、InterruptedException{
行++;
}
}
input1.txt    3
input2.txt    4
input3.txt    9
// no need for filename
context.write( new Text("blah"), new Text("1") );
public class LineMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
    protected long lines = 0;

    @Override
    protected void cleanup(Context context) throws IOException,
            InterruptedException {
        FileSplit split = (FileSplit) context.getInputSplit();
        String filename = split.getPath().toString();

        context.write(new Text(filename), new LongWritable(lines));
    }

    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        lines++;
    }
}