Hadoop多个文件单词计数

Hadoop的安装

    首先下载Hadoop的安装包,这里使用2.7.3版本。解压到/usr/local下

sudo tar -zxvf hadoop-2.7.3.tar.gz -C /usr/local/ 

    然后更改hadoop-2.7.3的属主

sudo chown -R jessin /usr/local/hadoop-2.7.3

    在/etc/profile下添加HADOOP_HOME环境变量,并将其bin放到PATH路径下:

export HADOOP_HOME=/usr/local/hadoop-2.7.3
export PATH=${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin:$PATH

    接着使配置立即生效:

source /etc/profile

    接下来在$HADOOP_HOME/etc/hadoop下修改或者添加四个文件,这时使用的是伪分布式,还是会使用HDFS。
    core-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>hadoop.tmp.dir</name>
        <value>file:/usr/local/hadoop-2.7.3/tmp</value>
        <description>Abase for other temporary directories.</description>
    </property>

    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

    hdfs-site.xml

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->

<configuration>
    <property>
        <name>dfs.replication</name>
        <value>1</value>
    </property>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/usr/local/hadoop-2.7.3/tmp/dfs/name</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/usr/local/hadoop-2.7.3/tmp/dfs/data</value>
    </property>
</configuration>

    mapred-site.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>

    yarn-site.xml

<?xml version="1.0"?>
<configuration>
<!-- Site specific YARN configuration properties -->
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
</configuration>

    必须在$HADOOP_HOME/etc/hadoop/hadoop-env.sh下添加JAVA_HOME的环境变量:

export JAVA_HOME=/usr/lib/jvm/jdk1.7.0

Hadoop的启动和终止

    格式化HDFS

hdfs namenode -format

    启动hdfs和yarn

start-dfs.sh
start-yarn.sh

    在hdfs下建立一个HOME文件夹

hadoop fs -mkdir /user/jessin

    结束Hadoop

stop-yarn.sh
stop-dfs.sh

单词计数程序

    单词计数程序是Hadoop的hello world程序,这里使用Maven来构建,需要在pom.xml添加如下两个jar:

<dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.3</version>
 </dependency>
 <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-mapreduce-client-core</artifactId>
            <version>2.7.3</version>
 </dependency>

    WordCount.java。需要注意的是Mapper和Reducer的泛型参数的前两个是输入的key,value类型,后两个是输出的key,value类型。

import java.io.IOException;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class WordCount {

  //TokenizerMapper继承Mapper类,并重写其map方法。
  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 {
   	//map方法中的value值存储的是文本文件中的一行信息(以回车符为行结束标记)。
	//map方法中的key值为该行的首字符相对与文本文件的首地址的偏移量。
	//StringTokenizer类将每一行拆分成一个个的单词,并将<word,1>作为map方法的结果输出。
	//其中IntWritable和Text类是Hadoop对int和String类的序列化封装,这些类能够被序列化,以便在分布式环境中进行数据交换。
      StringTokenizer itr = new StringTokenizer(value.toString());
      System.out.println("key : " + key + " value : " + value);
      while (itr.hasMoreTokens()) {
        word.set(itr.nextToken());
        context.write(word, one);//输出<key,value>为<word,one>
      }
    }
  }
  //IntSumReducer继承Reducer类,并重写其reduce方法。
  public static class IntSumReducer 
       extends Reducer<Text,IntWritable,Text,IntWritable> {
    private IntWritable result = new IntWritable();

    public void reduce(Text key, Iterable<IntWritable> values, 
                       Context context
                       ) throws IOException, InterruptedException {
	//reduce方法的输入参数key为单个单词;
	//而Iterable<IntWritable> values为各个Mapper上对应单词的计数值所组成的列表。
      int sum = 0;
      for (IntWritable val : values) {//遍历求和
        sum += val.get();
      }
      result.set(sum);
      context.write(key, result);//输出求和后的<key,value>
    }
  }

  //在MapReduce中,由Job对象负责管理和运行一个计算任务,并通过Job的一些方法对任务的参数进行相关的设置。
  public static void main(String[] args) throws Exception {
    Configuration conf = new Configuration();
    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
    if (otherArgs.length != 2) {
      System.err.println("Usage: wordcount <in> <out>");
      System.exit(2);
    }
    Job job = new Job(conf, "word count");
    job.setJarByClass(WordCount.class);
	//使用TokenizerMapper类完成Map过程;
    job.setMapperClass(TokenizerMapper.class);
	//使用IntSumReducer类完成Combiner过程;
    job.setCombinerClass(IntSumReducer.class);
	//使用IntSumReducer类完成Reducer过程;
    job.setReducerClass(IntSumReducer.class);
	//设置了Map过程和Reduce过程的输出类型,其中设置key的输出类型为Text;
    job.setOutputKeyClass(Text.class);
	//设置了Map过程和Reduce过程的输出类型,其中设置value的输出类型为IntWritable;
    job.setOutputValueClass(IntWritable.class);
	//设置任务数据的输入路径;
    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
	//设置任务输出数据的保存路径;
    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
	//调用job.waitForCompletion(true) 执行任务,执行成功后退出;
    System.exit(job.waitForCompletion(true) ? 0 : 1);
  }
}

    可以在根目录下打jar

mvn clean compile package

    结果如下:
这里写图片描述
    然后启动hadoop,在hdfs创建wordcount/input文件夹,将代码目录的的两个输入文件上传到hdfs

hadoop fs -mkdir -p wordcount/input
hadoop fs -put src/main/resources/input wordcount
hadoop fs -ls wordcount

    结果如下:
这里写图片描述
    在运行job之前,在HDFS上的输出文件夹必须不存在,否则会运行失败。可以使用以下命令删除HDFS上的文件夹。默认是用户的HOME目录:

hadoop fs -rm -r wordcount/output

    使用以下命令将job提交到hadoop运行,注意最后两个是HDFS上的输入和输出文件,倒数第三个WordCount是jar中的主函数:

hadoop jar ~/Documents/Program/final/hadoop_helloworld/target/hadoop-helloworld-1.0-SNAPSHOT.jar WordCount wordcount/input wordcount/output

    结果如下:
这里写图片描述
    在hdfs的wordcount/output下生成了两个文件,其中part-r-00000含有输出结果

hadoop fs -ls wordcount/output
hadoop fs -cat wordcount/output/part-r-00000

    运行结果如下:
这里写图片描述

单词计数源码下载

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值