题目如图所示
具体处理的数据如下
之前我写过一个MapReduce的词频统计实例
https://blog.csdn.net/qq_45683188/article/details/108365335
没有印象的朋友请看搜上面网址
词频统计的思路是在map阶段,将你的单词一个个的按照空格分开
然后形成hello-1和word-1的这样的形式,然后我们redece阶段再把它给加起来,这是一个大致的词频统计的思路
到了这个案例呢,我们发现,他并不是没有将数据相加,而是将这行数据进行处理,形成格式上的改变,相对于词频统计这就是发生很大的变化了。
那么相对于词频统计而言他的思路的差异在哪里发生了变化,代码方面又是那些发生了变化
首先就是思路阶段,我们在Map阶段的话,如何做
首先明白map阶段到底应该干点啥,之前的词频统计就是在map阶段把单词按照空格拆开,然后统计数据,循环一个个输入到reduce阶段的代码
如果从宏观的角度来讲的话,map阶段处理的就是数据,处理的就是一行行数据,然后将处理的结果传给reduce阶段
对于我们这个实例就是对数据进行格式上的处理,然后传给reduce
大致的思路就是这样,接下来就是代码部分了
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.json.simple.JSONObject;
import java.io.IOException;
public class WeaTherMap extends Mapper<LongWritable, Text,Text, NullWritable> {
String line=null;
Text k=new Text ();
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
line = new String(value.getBytes(),0,value.getLength(),"GBK");
String data[]=line.split (",");
//String data[]=line.split (" ");
JSONObject json=new JSONObject ();
json.put ("date",data[1]);
json.put ("temp",data[3]);
json.put ("city",data[0]);
json.put ("weather",data[2]);
json.put ("wind",data[4]);
k.set (json.toString ());
context.write (k,NullWritable.get ());
}
}
首先观察参数
<LongWritable, Text,Text, NullWritable>
LongWritable代表的是你的源文件的行数
Text代表的是你的这一行的内容
下一个Text代表的是你的处理后的内容
NullWritable,唉这个相对于词频统计的参数就是不一样了,为什么不一样呢
原因就是我们这个程序只对内容处理,词频统计是要统计行数的,所以需要IntWritable这个参数,这里我们既然不做任何处理,那么我们就是直接给他设为空
然后调用map方法,重写map方法,map方法就是处理一行数据调用一次
然后接下来就是map方法里面的内容了
首先你可能首先困惑的是这一句
line = new String(value.getBytes(),0,value.getLength(),"GBK");
这句话的作用在于何处,这句话的作用在于防止你的输出结果乱码,具体的原理我也不怎么清楚,记住这样就可,还有就是将你传入的数据转化为String类型的作用
然后接下来的代码可以说是我们的精髓所在了
String data[]=line.split (",");
//String data[]=line.split (" ");
JSONObject json=new JSONObject ();
json.put ("date",data[1]);
json.put ("temp",data[3]);
json.put ("city",data[0]);
json.put ("weather",data[2]);
json.put ("wind",data[4]);
首先就是按照,进行划分,然后放进我的data数组里
这里的处理是一行行的处理的
接下来额度这几行代码就是定义他的格式的代码
这个是使用了org.json.simple
具体的使用方法可以按照一个大佬的代码来具体使用
https://blog.csdn.net/kl28978113/article/details/79885805?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159921474419725222449777%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159921474419725222449777&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v3~pc_rank_v3-1-79885805.pc_ecpm_v3_pc_rank_v3&utm_term=json-simple&spm=1018.2118.3001.4187
然后转换,将处理后的数据转化为text类型,调用context方法一个个的给他传入过去
reduce阶段就是直接一个个的给他读出去了
具体的代码如下
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class WeatherReduce extends Reducer<Text, NullWritable,Text,NullWritable> {
@Override
protected void reduce(Text key, Iterable<NullWritable> values, Context context) throws IOException, InterruptedException {
context.write (key,NullWritable.get ());
}
}
这里需要注意的就是他的参数的设置问题了,传进了什么,应该传出去什么
然后就是Driver阶段的代码
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
public class Driver {
public static void main(String[] args) {
//设置输入和输出的路径
args=new String[2];
args[0]= "D:\\LIB\\hello.txt";
args[1]="D:\\LIB\\output";
//1:获取job信息
Configuration configuration=new Configuration ();
try {
Job job=Job.getInstance (configuration);
//2:获取jar包信息
job.setJarByClass (Driver.class);
//3:关联自定义的mapper和reduceer
job.setMapperClass (WordCountMapper.class);
job.setReducerClass (WordCountReducer.class);
//4:设置map输出类型数据
job.setMapOutputKeyClass (Text.class);
job.setMapOutputValueClass (IntWritable.class);
//5:设置最终输出数据类型
job.setOutputKeyClass (Text.class);
job.setOutputValueClass (IntWritable.class);
//以下的的四行代码设立的原因是为了解决你的输出目录已经存在文件的情况,如果你的输出目录已经存在文件夹,那么你是无法进行输出的
//所以我们就对进行检测,如果存在就把他删了
Path path = new Path(args[1]);// 取第1个表示输出目录参数(第0个参数是输入目录)
FileSystem fileSystem = path.getFileSystem(configuration);// 根据path找到这个文件
if (fileSystem.exists(path)) {
fileSystem.delete(path, true);// true的意思是,就算output有东西,也一带删除
}
//6:设置数据输入和输出文件路径
FileInputFormat.setInputPaths (job,new Path (args[0]));
FileOutputFormat.setOutputPath (job,new Path (args[1]));
boolean a = job.waitForCompletion (true);
System.out.println (a );
} catch (IOException e) {
e.printStackTrace ( );
} catch (InterruptedException e) {
e.printStackTrace ( );
} catch (ClassNotFoundException e) {
e.printStackTrace ( );
}
//提交代码
}
}
执行结果如图所示
以上就是我对于用MapReduce给天气预报数据规范格式并且输出的大致思路过程以及代码部分了