本地不搭建任何hadoop环境,就使用maven管理hadoop必要依赖
使用远程hadoop搭建好的集群即可
首先你要有hadoop集群,至于怎么集群,这里就不说了,很麻烦
启动你的hadoop
上传你要统计的数据到hdfs --一个或多个文件 记住该路径, 我这个文件作为测试,324M够大了
搭建本地idea的hadoop项目
创建maven项目
pom.xml 依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!--<dependency>-->
<!--<groupId>org.apache.hadoop</groupId>-->
<!--<artifactId>hadoop-core</artifactId>-->
<!--<version>1.2.1</version>-->
<!--</dependency>-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.3</version>
</dependency>
<!-- hdfs-->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>2.7.3</version>
</dependency>
</dependencies>
<!--添加apache源-->
<repositories>
<repository>
<id>apache</id>
<url>http://maven.apache.org</url>
</repository>
</repositories>
找个包创建一个测试类
注释都写得明明白白
package testBigDate;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
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 java.io.IOException;
import java.util.StringTokenizer;
/** 统计每个单词在文件中的数量
* @author huangchao
* @date 2020/9/10
*/
public class TestWordCount {
/**
* 下面是Mapper类中的4个泛型含义:
* a.泛型一:KEYIN:Object,对应的Mapper的输入key。输入key是每行的行首偏移量
* b.泛型二: VALUEIN:Text,对应的Mapper的输入Value。输入value是每行的内容
* c.泛型三:KEYOUT:Text 对应的Mapper的输出key,根据业务来定义, 例如现在统计的每个单词的数量,则maper输出的key应该是某个单词
* d.泛型四:VALUEOUT:IntWritable 对应的Mapper的输出value,根据业务来定义, 例如现在统计的每个单词的数量,则maper输出的value应该是这个单词对应的数量
*/
public static class WordMapper extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1);
private Text word = new Text();
/**
* 每读一行数据, 都会执行一次map
*/
@Override
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
//System.out.println("数据的偏移量是 :" + key);
//System.out.println("本次读取到的数据是 : " + value);
// 开始记录这一行单词出现次数
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
word.set(itr.nextToken());
context.write(word, one);
}
}
}
/**
* Reducer组件用于接收Mapper组件的输出
* 1.reduce的输入KEYIN,VALUEIN需要和mapper的输出key,value类型保持一致
* 2.reduce的输出KEYOUT,VALUEOUT类型,根据具体业务决定
* reduce收到map的输出,会按相同的key做聚合,形成:key Iterable 形式然后通过reduce方法进行传递
* 5. reduce方法中的Iterable是一次性的,即遍历一次之后,再遍历,里面就没有数据了。
* 所以,在某些业务场景,会涉及到多次操作此迭代器,处理的方法是
* :①先创建一个List ②把Iterable装到List ③多次去使用List即可
*/
public static class WordReduce extends Reducer<Text,IntWritable,Text,IntWritable> {
private IntWritable result = new IntWritable();
@Override
public void reduce(Text key, Iterable<IntWritable> values,Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable val : values) {
sum += val.get();
}
result.set(sum);
context.write(key, result);
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
System.setProperty("HADOOP_USER_NAME", "huangchao");
Configuration conf = new Configuration();
conf.set("fs.defaultFS", "hdfs://nn2.hadoop:9000");
conf.set("mapreduce.app-submission.cross-platform", "true");
//jar包运行地址
conf.set("mapred.jar", "D:\\ITproject\\demo\\bigdata\\bigdata-test\\target\\bigdata-test-1.0-SNAPSHOT.jar");
conf.set("fs.hdfs.impl", org.apache.hadoop.hdfs.DistributedFileSystem.class.getName());
Job job = Job.getInstance(conf, "wordCount"); //任务名称
job.setJarByClass(TestWordCount.class);//要执行的jar中的类
//设置输入文件类型--文本类型
//job.setInputFormatClass(TextInputFormat.class);
//job.setOutputFormatClass(TextOutputFormat.class);
//设置自己程序的mapReduce
job.setMapperClass(WordMapper.class);
job.setCombinerClass(WordReduce.class);
job.setReducerClass(WordReduce.class);
//结果key的输出类型和结果value的输出类型
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
//判断输出路径是否存在,存在则删除
FileSystem fs = FileSystem.get(conf);
//Path op = new Path("hdfs://nn2.hadoop:9000/user/data/output");
Path op = new Path(args[1]);
if(fs.exists(op)){
// 递归删除目录与目录内容
fs.delete(op,true);
System.out.println("已删除!");
}
//设置输入路径和输出路径 ,这里路径就不在这里写死了,在jvm启动参数中传的
//FileInputFormat.addInputPath(job, new Path("hdfs://nn2.hadoop:9000/user/data/input2"));
//FileOutputFormat.setOutputPath(job, new Path("hdfs://nn2.hadoop:9000/user/data/output"));
FileInputFormat.addInputPath(job, new Path(args[0]));
FileOutputFormat.setOutputPath(job, new Path(args[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
下载hadoop.dll文件,百度随便搜索hadoop.dll到处都是 只要hadoop.dll,放到你的C:\Windows\System32文件夹下,以免出现一些不必要的错误
添加项目启动参数,你的远程服务器数据输入地址,和结果输出地址,最好写绝对路径
clean package 打包一波
然后再运行一波main方法结果 自动创建了一个output文件夹,并返回成功_SUCCESS,和结果part-r-00000两个文件
不止到part-r-0000为什么不能预览,谁找到答案记得告诉我
既然idea中看不了结果,我们去服务器看一些结果
原数据文件内容大致如下