第一个完整的Map/Reduce小程序
2014-07-06 09:23
316 查看
从在自己的win7下面装好虚拟机,然后在虚拟机上面安装hadoop,然后再安装hadoop-eclipse插件,过去好像有一个星期了,之前装虚拟机和hadoop都没成功,上个星期解除了封印,一口气把hadoop学习前期的所有的东西都搞定了,接下来就是遥遥无期的hadoop之路。希望自己能坚持下去。
今天按着别人的思路在win7下面的eclipse里面敲了算是处女作的Map/Reduce程序,虽然很简单,但是自己还是一步一步的走通了,因为hadoop是安装在虚拟机上的,但是eclipse是在win7下面,所以在中间运行的时候会有一系列的错误,昨天晚上把遇到的问题百度的百度,问神的问神,烧香的烧香,基本上都解决了,现在能把程序跑起来,感觉自己的熬夜什么的都没有白费
下面把一个完整的Map/Reduce程序贴出来,算是一个开始,也是一个纪念嘛!
问题描述:
先上数据:
13599999999 10086
13899999999 120
13944444444 110
13722222222 110
18800000000 120
13722222222 10086
18944444444 10086
要求是把拨打过同一个电话的电话输出来比如:
110 13944444444,13722222222
接下来就是Map/Reduce函数,Map函数将每一行数据读入,然后进行分割,分割成<key,value>的格式
上面的key相当于110,value相当于13944444444,也就是数据前面的是value,后面的是key,代码如下:
接下就是Reduce类,Reduce类要做的就是把从Map传入来的数据进行整合,将Map中具有相同key值的value
进行迭代,代码如下(需要知道的是,Map函数的输出也就是Reduce函数的输入,所以在写里面的reduce函 数的时候要注意参数的类型要和上面Map的输出值的类型相对应):
接下来就是贴出整个程序,里面有个枚举是用来记录数据错误的时候进行一个计数,还有一个run方法是重写 了主类实现的接口的方法,每个Map/Reduce程序里面run方法里面书写的套路基本上都是一样的,main方 法里面书写的套路基本上也都是一样的,只要改一下主类的名字就可以了
传好数据,
做好配置:在项目上右键,选择Run as 下面的 Run connfigruations,前面的Main填上项目的名字,然后填上主类的名字,接下来的Arguments写上linux下面hdfs中存放文件的路径和输出结果的路径,最后点击Apply 然后点击run
运行结果 :刷新右边DFS Locations 下面的root目录,下面就出现了你在上一步Arguments处填写的输出目录,需要注意的是运行前要保证 root目录下面的没有和你在Argments填写时同名的输出结果的目录,
双击我们的输出目录下面的part-r-00000,就可以看到我们想要的结果了:
细心的数一下,我们的数据是不是少了一条,原因是我们给的数据上面的格式不对,仔细看上面的的第二条数据,可以知道中间不是只空了一个空格,所以这一条数据就被跳过了。
心得:写完第一个Map/Reduce函数,之前也看过几个,感觉模式基本上是一样的,需要记得的就是Map函数的输出结果是Reduce函数的输入,因此在写Map方法和Reduce方法的时候就要注意里面的参数的类型要保持一致,否则会出错,其他的
就基本上按照套路来就可以了,按照不同的需求写 出不同的方法,模板就感觉只有一个。
转载请注明原文链接http://mntms.iteye.com/blog/2086410 点击打开链接
今天按着别人的思路在win7下面的eclipse里面敲了算是处女作的Map/Reduce程序,虽然很简单,但是自己还是一步一步的走通了,因为hadoop是安装在虚拟机上的,但是eclipse是在win7下面,所以在中间运行的时候会有一系列的错误,昨天晚上把遇到的问题百度的百度,问神的问神,烧香的烧香,基本上都解决了,现在能把程序跑起来,感觉自己的熬夜什么的都没有白费
下面把一个完整的Map/Reduce程序贴出来,算是一个开始,也是一个纪念嘛!
问题描述:
先上数据:
13599999999 10086
13899999999 120
13944444444 110
13722222222 110
18800000000 120
13722222222 10086
18944444444 10086
要求是把拨打过同一个电话的电话输出来比如:
110 13944444444,13722222222
接下来就是Map/Reduce函数,Map函数将每一行数据读入,然后进行分割,分割成<key,value>的格式
上面的key相当于110,value相当于13944444444,也就是数据前面的是value,后面的是key,代码如下:
public static class Map extends Mapper<LongWritable, Text, Text, Text> { public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); // 读取源数据 try { // 数据处理 String[] lineSplit = line.split(" "); // 将数据分割 String anum = lineSplit[0]; String bnum = lineSplit[1]; context.write(new Text(bnum), new Text(anum)); // 输出 } catch (java.lang.ArrayIndexOutOfBoundsException e) { context.getCounter(Counter.LINESKIT).increment(1); // 出错令计数器加1 return; } } }
接下就是Reduce类,Reduce类要做的就是把从Map传入来的数据进行整合,将Map中具有相同key值的value
进行迭代,代码如下(需要知道的是,Map函数的输出也就是Reduce函数的输入,所以在写里面的reduce函 数的时候要注意参数的类型要和上面Map的输出值的类型相对应):
public static class Reduce extends Reducer<Text, Text, Text, Text> { //Iterable<> 使用一个迭代器将数据保存起来 public void reduce(Text key,Iterable<Text> values,Context context) throws IOException, InterruptedException { String valueString; String out = ""; for(Text value : values) { valueString = value.toString(); out += valueString+","; } context.write(key, new Text(out)); } }
接下来就是贴出整个程序,里面有个枚举是用来记录数据错误的时候进行一个计数,还有一个run方法是重写 了主类实现的接口的方法,每个Map/Reduce程序里面run方法里面书写的套路基本上都是一样的,main方 法里面书写的套路基本上也都是一样的,只要改一下主类的名字就可以了
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
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.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class Test_2 extends Configured implements Tool {
enum Counter {
LINESKIT, // 出错的行
}
public static class Map extends Mapper<LongWritable, Text, Text, Text> { public void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String line = value.toString(); // 读取源数据 try { // 数据处理 String[] lineSplit = line.split(" "); // 将数据分割 String anum = lineSplit[0]; String bnum = lineSplit[1]; context.write(new Text(bnum), new Text(anum)); // 输出 } catch (java.lang.ArrayIndexOutOfBoundsException e) { context.getCounter(Counter.LINESKIT).increment(1); // 出错令计数器加1 return; } } }
public static class Reduce extends Reducer<Text, Text, Text, Text> { //Iterable<> 使用一个迭代器将数据保存起来 public void reduce(Text key,Iterable<Text> values,Context context) throws IOException, InterruptedException { String valueString; String out = ""; for(Text value : values) { valueString = value.toString(); out += valueString+","; } context.write(key, new Text(out)); } }
@Override
public int run(String[] args) throws Exception {
Configuration conf =getConf();
Job job = new Job(conf,"Test_2"); //任务名:主类的名字
job.setJarByClass(Test_2.class); //指定class
FileInputFormat.addInputPath(job, new Path(args[0])); //指定输入路径
FileOutputFormat.setOutputPath(job, new Path(args[1])); //指定输出路径
job.setMapperClass(Map.class); //调用上面的Map类作为Map任务代码
job.setReducerClass(Reduce.class); //调用上面的Reduce类做为Reduce任务代码
job.setOutputFormatClass(TextOutputFormat.class);
job.setOutputKeyClass(Text.class); //指定输出的key的格式
job.setOutputValueClass(Text.class); //指定输出的value的格式
job.waitForCompletion(true);
return job.isSuccessful()?1:0;
}
public static void main(String[] args) throws Exception {
//main 方法运行
int res = ToolRunner.run(new Configuration(),new Test_2(),args);
System.exit(res);
}
}
传好数据,
做好配置:在项目上右键,选择Run as 下面的 Run connfigruations,前面的Main填上项目的名字,然后填上主类的名字,接下来的Arguments写上linux下面hdfs中存放文件的路径和输出结果的路径,最后点击Apply 然后点击run
运行结果 :刷新右边DFS Locations 下面的root目录,下面就出现了你在上一步Arguments处填写的输出目录,需要注意的是运行前要保证 root目录下面的没有和你在Argments填写时同名的输出结果的目录,
双击我们的输出目录下面的part-r-00000,就可以看到我们想要的结果了:
细心的数一下,我们的数据是不是少了一条,原因是我们给的数据上面的格式不对,仔细看上面的的第二条数据,可以知道中间不是只空了一个空格,所以这一条数据就被跳过了。
心得:写完第一个Map/Reduce函数,之前也看过几个,感觉模式基本上是一样的,需要记得的就是Map函数的输出结果是Reduce函数的输入,因此在写Map方法和Reduce方法的时候就要注意里面的参数的类型要保持一致,否则会出错,其他的
就基本上按照套路来就可以了,按照不同的需求写 出不同的方法,模板就感觉只有一个。
转载请注明原文链接http://mntms.iteye.com/blog/2086410 点击打开链接
相关文章推荐
- 第一个完整的Map/Reduce小程序
- WordCount------自己写的第一个map/reduce程序------
- 在eclipse下跑第一个map-reduce程序-转载分享
- hadoop学习之第一个Map/Reduce程序
- Python 初学——V_Rename(第一个完整的python程序)
- 第一个完整的python程序---统计python3的所有包中,以哪个字母开头的最多?
- Hadoop 使用Combiner提高Map/Reduce程序效率
- Hadoop Map/Reduce 示例程序WordCount
- Hadoop 使用Combiner提高Map/Reduce程序效率
- 开始玩hadoop8--hadoop 2.6.0实战(第一个reduce程序,ubuntu 14.04)倒排索引
- 第一个完整的程序。著名的俄罗斯方块
- 基于 shell streaming的 Map/Reduce程序
- 终于完成了第一个完整的编译程序
- 用hadoop-streaming 运行python map-reduce程序
- hadoop——在命令行下编译并运行map-reduce程序
- 我的第一个map/reduce 作业
- 第一个Android的完整程序(UDP通讯工具)
- 我的第一个完整游戏程序:俄罗斯方块
- 自己完成的第一个Map-Reduce, 类似模板匹配
- Hadoop 使用Combiner提高Map/Reduce程序效率