环境:
java 1.8.0
hadoop 2.7.7
windows 10
java和hadoop安装路径不能有空格,不然后面会报错,包括IDEA中设置的java路径

如果没有安装hadoop,请看Windows安装Hadoop

一、IDEA新建Maven项目,项目名称和包名随便取,本项目的项目名为mapreduce-test

二、项目结构

其中hdfs包并没有用到,所以不需要

idea 开发 hadoop spark idea创建hadoop项目_apache

三、项目文件的代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.hadoop</groupId>
    <artifactId>mapreduce-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-core</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-common</artifactId>
            <version>2.7.7</version>
        </dependency>

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>2.7.7</version>
        </dependency>

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

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

    </dependencies>
</project>

Tools.java
需要强调的是,MapReduce项目中,如果输出目录已经存在,就会报错。所以setOutPut方法中先判断输出目录是否已经存在,如果已经存在,那么就先删除这个目录以及目录中所有的内容,再创建该项目。

package com.hadoop.utils;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class Tools {

    public static final Configuration configuration = new Configuration();

    static {
        configuration.set("fs.defaultFS", "hdfs://localhost:9000");

        try {
            // 设置 HADOOP_HOME 目录
            System.setProperty("hadoop.home.dir", "D:/hadoop-2.7.7/");
            // 加载库文件
            System.load("D:/hadoop-2.7.7/bin/hadoop.dll");
        } catch (UnsatisfiedLinkError e) {
            System.err.println("Native code library failed to load.\n" + e);
            System.exit(1);
        }
    }

    public static Job getJob() {
        Job job = null;
        try {
            job = Job.getInstance(configuration);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return job;
    }

    public static void setMapper(Job job, Class mapperClass, Class keyClass, Class valueClass) {
        job.setMapperClass(mapperClass);
        job.setMapOutputKeyClass(keyClass);
        job.setMapOutputValueClass(valueClass);
    }

    public static void setReduce(Job job, Class reduceClass, Class keyClass, Class valueClass) {
        job.setReducerClass(reduceClass);
        job.setOutputKeyClass(keyClass);
        job.setOutputValueClass(valueClass);
    }

    public static void setInput(Job job, String path) {
        try {
            FileInputFormat.addInputPath(job, new Path(path));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void setOutPut(Job job, String path) {
        try {
            FileSystem fileSystem = null;
            fileSystem = FileSystem.get(configuration);
            Path path1 = new Path(path);
            if(fileSystem.exists(path1)){
                // 如果存在,就rm -a
                fileSystem.delete(path1, true);
            }
            FileOutputFormat.setOutputPath(job, new Path(path));
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

}

CountMapper.java

package com.hadoop.mapper;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class CountMapper extends Mapper<LongWritable, Text, Text, LongWritable> {
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        if (value != null) {
            String realValue = String.valueOf(value);
            context.write(new Text(realValue), new LongWritable(1));
        }
    }

}

CountReduce.java

package com.hadoop.reducer;

import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;
import java.util.Iterator;

public class CountReduce extends Reducer<Text, LongWritable, Text, LongWritable> {

    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
        int total = 0;
        Iterator<LongWritable> iterator = values.iterator();
        while (iterator.hasNext()) {
            total += Integer.valueOf(String.valueOf(iterator.next()));
        }
        context.write(key, new LongWritable(total));
    }
}

CountMain.java

package com.hadoop.mapreduce;

import com.hadoop.mapper.CountMapper;
import com.hadoop.reducer.CountReduce;
import com.hadoop.utils.Tools;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;

public class CountMain {
    public static void main(String[] args1) {
        try {
            Job job = Tools.getJob();

            job.setJarByClass(CountMain.class);

            Tools.setMapper(job, CountMapper.class, Text.class, LongWritable.class);

            Tools.setReduce(job, CountReduce.class, Text.class, LongWritable.class);
            // 输入路径可以是一个文件,也可以是一个目录
            // 如果输入路径是一个目录时,扫描该目录下的所有文件
            Tools.setInput(job, "/hadoop/mapred_input");
            // 输出路径要求是一个不存在的文件夹
            Tools.setOutPut(job, "/hadoop/mapred_output");


            job.waitForCompletion(true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

log4j.properties文件是从hadoop根目录/etc/hadoop 目录下拷贝过来的。

四、上传输入文件

  1. 在D:\hadoop-2.7.7\input_dir目录下新建了一个文件,test_file.txt,文件内容如下:
46494
46494
46494
46462
46462
46500
46500
46494
46462
46462
46462
46538
  1. 运行hadoop,打开dos窗口

使用hadoop shell命令创建文件夹,如下。其中path就是要创建的目录的路径。更多的hadoop shell命令可以看参考文章。

hadoop fs -mkdir path

创建完成后可以使用hadoop shell命令查看文件目录,如下。其中-R表示循环遍历所有的子目录,/表示从根目录开始。

hadoop fs -ls -R /

我的项目创建完后显示出来是这样子的:

idea 开发 hadoop spark idea创建hadoop项目_apache_02


接着把本地的写好的文件上传到hadoop服务器中,如下。上传是否成功可以用ls

hadoop fs -put D:\\hadoop-2.7.7\\input_dir\\test_file.txt /hadoop/mapred_input/
  1. 运行MapReduce项目

运行好之后/hadoop/mapred_ouput目录下就会产生两个文件,其中part-r-00000就是运算的结果

idea 开发 hadoop spark idea创建hadoop项目_hadoop_03


可以查看该文件的内容,就是运算的结果

hadoop fs -cat /hadoop/mapred_output/part-r-00000

idea 开发 hadoop spark idea创建hadoop项目_hadoop_04

五、遇到的错误
这里记录一下项目中遇到的报错,当然上面第三点给出的代码是最终代码。

报错信息

java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Z

解决方法:
首先查看%HADOOP_HOME%\bin中是否存在hadoop.dll这个文件,如果不存在,就说明下载过来的hadoop是linux版本的,不完整。需要下载hadooponwindows-master.zip,下载地址。再用hadooponwindows-master.zip中的bin文件夹替换%HADOOP_HOME%\bin文件夹

最后在代码中手动加载该文件

//这是部分代码,完整代码见上面的Tools.java文件
try {
// 设置 HADOOP_HOME 目录
    System.setProperty("hadoop.home.dir", "D:/hadoop-2.7.7/");
    // 加载库文件
    System.load("D:/hadoop-2.7.7/bin/hadoop.dll");
} catch (UnsatisfiedLinkError e) {
    System.err.println("Native code library failed to load.\n" + e);
    System.exit(1);
}

参考文章:
java.lang.UnsatisfiedLinkError: org.apache.hadoop.io.nativeio.NativeIO$Windows.access0(Ljava/lang/String;I)Zidea本地运行mapreduce程序hadoop 命令