栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 云计算 > 云平台

大数据 MapReduce编程实践(1)编程实现文件合并和去重操作

云平台 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

大数据 MapReduce编程实践(1)编程实现文件合并和去重操作

一、实验目的

1.通过实验掌握基本的MapReduce编程方法;
2.掌握用MapReduce解决一些常见的数据处理问题,包括数据去重、数据排序和数据挖掘等。

二、实验平台

已经配置完成的Hadoop伪分布式环境。

三. 实验内容和要求 (1)编程实现文件合并和去重操作

对于两个输入文件,即文件A和文件B,请编写MapReduce程序,对两个文件进行合并,并剔除其中重复的内容,得到一个新的输出文件C。下面是输入文件和输出文件的一个样例供参考。
输入文件A的样例如下:
20150101 x
20150102 y
20150103 x
20150104 y
20150105 z
20150106 x

输入文件B的样例如下:
20150101 y
20150102 y
20150103 x
20150104 z
20150105 y

根据输入文件A和B合并得到的输出文件C的样例如下:
20150101 x
20150101 y
20150102 y
20150103 x
20150104 y
20150104 z
20150105 y
20150105 z
20150106 x

需要首先删除HDFS中与当前Linux用户hadoop对应的input和output目录(即HDFS中的“/user/hadoop/input”和“/user/hadoop/output”目录),这样确保后面程序运行不会出现问题

cd /usr/local/hadoop
./bin/hdfs dfs -rm -r input
./bin/hdfs dfs -rm -r output

然后,再在HDFS中新建与当前Linux用户hadoop对应的input目录,即“/user/hadoop/input”目录

cd /usr/local/hadoop
./bin/hdfs dfs -mkdir input

创建A.txt B.txt,输入上述内容

vi A.txt
vi B.txt

将A,B上传到HDFS中

cd /usr/local/hadoop
./bin/hdfs dfs -put ./A.txt input
./bin/hdfs dfs -put ./B.txt input

运行代码:

import java.io.IOException;
 
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 Merge {

	
	//重载map函数,直接将输入中的value复制到输出数据的key上
	public static class Map extends Mapper{
		private static Text text = new Text();
		public void map(Object key, Text value, Context context) throws IOException,InterruptedException{
			text = value;
			context.write(text, new Text(""));
		}
	}
	
	//重载reduce函数,直接将输入中的key复制到输出数据的key上
	public static class Reduce extends Reducer{
		public void reduce(Text key, Iterable values, Context context ) throws IOException,InterruptedException{
			context.write(key, new Text(""));
		}
	}
	
	public static void main(String[] args) throws Exception{
		
		// TODO Auto-generated method stub
		Configuration conf = new Configuration();
        conf.set("fs.default.name","hdfs://localhost:9000");
		String[] otherArgs = new String[]{"input","output"}; 
		if (otherArgs.length != 2) {
			System.err.println("Usage: wordcount  ");
			System.exit(2);
			}
		Job job = Job.getInstance(conf,"Merge and duplicate removal");
		job.setJarByClass(Merge.class);
		job.setMapperClass(Map.class);
		job.setCombinerClass(Reduce.class);
		job.setReducerClass(Reduce.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
		FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
		System.exit(job.waitForCompletion(true) ? 0 : 1);
	}

}

编译运行:

查看实验结果:

cd /usr/local/hadoop
./bin/hdfs dfs -cat output
	//map函数读取输入中的value,将其转化成IntWritable类型,最后作为输出key
	public static class Map extends Mapper{
		
		private static IntWritable data = new IntWritable();
		public void map(Object key, Text value, Context context) throws IOException,InterruptedException{
			String text = value.toString();
			data.set(Integer.parseInt(text));
			context.write(data, new IntWritable(1));
		}
	}
	
	//reduce函数将map输入的key复制到输出的value上,然后根据输入的value-list中元素的个数决定key的输出次数,定义一个全局变量line_num来代表key的位次
	public static class Reduce extends Reducer{
		private static IntWritable line_num = new IntWritable(1);
		
		public void reduce(IntWritable key, Iterable values, Context context) throws IOException,InterruptedException{
			for(IntWritable val : values){
				context.write(line_num, key);
				line_num = new IntWritable(line_num.get() + 1);
			}
		}
	}
	
	//自定义Partition函数,此函数根据输入数据的最大值和MapReduce框架中Partition的数量获取将输入数据按照大小分块的边界,然后根据输入数值和边界的关系返回对应的Partiton ID
	public static class Partition extends Partitioner{
		public int getPartition(IntWritable key, IntWritable value, int num_Partition){
			int Maxnumber = 65223;//int型的最大数值
			int bound = Maxnumber/num_Partition+1;
			int keynumber = key.get();
			for (int i = 0; i
				if(keynumber=bound * i){
					return i;
				}
			}
			return -1;
		}
	}
	
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		Configuration conf = new Configuration();
        conf.set("fs.default.name","hdfs://localhost:9000");
		String[] otherArgs = new String[]{"input","output"}; 
		if (otherArgs.length != 2) {
			System.err.println("Usage: wordcount  ");
			System.exit(2);
			}
        Job job = Job.getInstance(conf,"Merge and sort");
		job.setJarByClass(Merge.class);
		job.setMapperClass(Map.class);
		job.setReducerClass(Reduce.class);
		job.setPartitionerClass(Partition.class);
		job.setOutputKeyClass(IntWritable.class);
		job.setOutputValueClass(IntWritable.class);
		FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
		FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
		System.exit(job.waitForCompletion(true) ? 0 : 1);

	}

}

编译运行:

查看实验结果:

cd /usr/local/hadoop
./bin/hdfs dfs -cat output
	//Map将输入文件按照空格分割成child和parent,然后正序输出一次作为右表,反序输出一次作为左表,需要注意的是在输出的value中必须加上左右表区别标志
	public static class Map extends Mapper{
		public void map(Object key, Text value, Context context) throws IOException,InterruptedException{
			String child_name = new String();
			String parent_name = new String();
			String relation_type = new String();
			String line = value.toString();
			int i = 0;
			while(line.charAt(i) != ' '){
				i++;
			}
			String[] values = {line.substring(0,i),line.substring(i+1)};
			if(values[0].compareTo("child") != 0){
				child_name = values[0];
				parent_name = values[1];
				relation_type = "1";//左右表区分标志
				context.write(new Text(values[1]), new Text(relation_type+"+"+child_name+"+"+parent_name));
				//左表
				relation_type = "2";
				context.write(new Text(values[0]), new Text(relation_type+"+"+child_name+"+"+parent_name));
				//右表
			}
		}
	}
	
	public static class Reduce extends Reducer{
		public void reduce(Text key, Iterable values,Context context) throws IOException,InterruptedException{
			if(time == 0){   //输出表头
				context.write(new Text("grand_child"), new Text("grand_parent"));
				time++;
			}
			int grand_child_num = 0;
			String grand_child[] = new String[10];
			int grand_parent_num = 0;
			String grand_parent[]= new String[10];
			Iterator ite = values.iterator();
			while(ite.hasNext()){
				String record = ite.next().toString();
				int len = record.length();
				int i = 2;
				if(len == 0) continue;
				char relation_type = record.charAt(0);
				String child_name = new String();
				String parent_name = new String();
				//获取value-list中value的child
				
				while(record.charAt(i) != '+'){
					child_name = child_name + record.charAt(i);
					i++;
				}
				i=i+1;
				//获取value-list中value的parent
				while(i
					parent_name = parent_name+record.charAt(i);
					i++;
				}
				//左表,取出child放入grand_child
				if(relation_type == '1'){
					grand_child[grand_child_num] = child_name;
					grand_child_num++;
				}
				else{//右表,取出parent放入grand_parent
					grand_parent[grand_parent_num] = parent_name;
					grand_parent_num++;
				}
			}

			if(grand_parent_num != 0 && grand_child_num != 0 ){
				for(int m = 0;m
					for(int n=0;n
						context.write(new Text(grand_child[m]), new Text(grand_parent[n]));
						//输出结果
					}
				}
			}
		}
	}
	public static void main(String[] args) throws Exception{
		// TODO Auto-generated method stub
		Configuration conf = new Configuration();
        conf.set("fs.default.name","hdfs://localhost:9000");
		String[] otherArgs = new String[]{"input","output"}; 
		if (otherArgs.length != 2) {
			System.err.println("Usage: wordcount  ");
			System.exit(2);
			}
        Job job = Job.getInstance(conf,"Single table join ");
		job.setJarByClass(Merge.class);
		job.setMapperClass(Map.class);
		job.setReducerClass(Reduce.class);
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
		FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
		System.exit(job.waitForCompletion(true) ? 0 : 1);
	}
}

编译运行:

查看实验结果:

cd /usr/local/hadoop
./bin/hdfs dfs -cat output/*

四、实验遇到的问题

问题1:

解决方法:引入hdfs包

问题2:

解决方法:hdfs的output目录已经存在,删除即可

问题三:

解决方法:引入yarn包

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/897361.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号