MapReduce数据处理两表join连接

现在这里有两个text文档,需要把它合并成一个文档,并且里面的数据不能有冗余..

info.txt文件:

1003 kaka
1004 da
1005 jue
1006 zhao

cpdata.txt文件:

201001 1003 abc
201002 1005 def
201003 1006 ghi
201004 1003 jkl
201005 1004 mno
201006 1005 pqr
201001 1003 abc
201004 1003 jkl
201006 1005 mno
200113 1007 zkl

生成文件:

1003	201001 abc kaka
1003	201004 jkl kaka
1004	201005 mno da
1005	201002 def jue
1005	201006 pqr jue
1005	201006 mno jue
1006	201003 ghi zhao

这里先申明下,这个纯属个人想法,如果有跟好的方法可以告诉我

   因为info.txt文档的第一个字段与cpdata.txt的第二个字段是相同的,所以我把他们做为key值,这样通过Map他们就会组合了.去冗余,

              主要是用了个List记录已经读取过的变量,如果有一样的就不读取了.

代码如下:

public class Advanced extends Configured implements Tool {

	public static class AdMap extends Mapper<LongWritable, Text, Text, TextPair>{

		@Override
		protected void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
			// TODO Auto-generated method stub
//		 	String filePath = ((FileSplit)context.getInputSplit()).getPath().toString();
			Text word = new Text();
		 	
		 	String line = value.toString();
		 	String[] childline = line.split(" ");    //以空格截取
			       //判断是哪一张表,其实个人觉得这样判断还不合理,可以使用上面注视掉的获取路径值来判断
                               if(childline.length == 3){
					 TextPair pair = new TextPair();
					 pair.setFlag("0");         //这是个标识   0.表示 cpdata.txt     1表示info.txt
					 pair.setKey(childline[1]);
					 pair.setValue(childline[0]+" "+childline[2]);
					 pair.setContent(pair.toString());
					 word.clear();
					 word.set(pair.getKey());
                                         context.write(word, pair);        //传递一个对象要实现WritableComparable接口
				}else{
					TextPair pair = new  TextPair();
					pair.setFlag("1");
					pair.setKey(childline[0]);
					pair.setValue(childline[1]);
					pair.setContent(pair.toString());
					word.clear();
					word.set(pair.getKey());
					context.write(word, pair);
				}
			
			
		}
		
	}
	
	public static class AdReduce extends Reducer<Text, TextPair, Text, Text>{

		@Override
		public void reduce(Text key, Iterable<TextPair> values,
				Context context)
				throws IOException, InterruptedException {
			// TODO Auto-generated method stub
                        //list0装载的都是cpdata的数据,list1装载的是info的数据
                        List<Text> list0 = new ArrayList<Text>();     
			List<Text> list1 = new ArrayList<Text>();
			Iterator<TextPair> it = values.iterator();
			TextPair pair = new TextPair();
			while(it.hasNext()){
					pair = it.next();
				if("1".equals(pair.getFlag()))
					list1.add(new Text(pair.getValue()));
				else 
					list0.add(new Text(pair.getValue()));
			}
			
			List<Text> sublist = new ArrayList<Text>();       //sublist用来添加已经写过的数据,然后再判断,如果存在就不用操作
			for(int i = 0 ; i<list1.size(); i++){
				for(int j = 0 ;j<list0.size();j++){
					if(!sublist.contains(list0.get(j))){
						sublist.add(list0.get(j));
						context.write(key, new Text(list0.get(j)+" " +list1.get(i)));
					}
				}
			}
			
			
		}
		
	}
	
	
	
	
	
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
                       int res = ToolRunner.run(new Configuration(), new Advanced(), args);
			System.exit(res);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public int run(String[] args) throws Exception {
		Configuration conf = new Configuration();
		
		FileSystem fs = FileSystem.get(conf);
		if(fs.exists(new Path(args[2]))){
                        //如果文件已近存在就删除文件
//			System.out.println("error : file is exists");
//			System.exit(-1);
			fs.delete(new Path(args[2]), true);
		}
		
		Job job = new Job(conf , "Advanced");
		job.setJarByClass(Advanced.class);
		job.setMapperClass(AdMap.class);
		job.setReducerClass(AdReduce.class);
		
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(TextPair.class);
		
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(Text.class);
		
		FileInputFormat.setInputPaths(job, new Path(args[0]),new Path(args[1]));
		FileOutputFormat.setOutputPath(job, new Path(args[2]));
		return job.waitForCompletion(true) ? 0 : 1;
	}
	
	
	
	public static class TextPair implements WritableComparable<TextPair>{

		public String getValue() {
			return value;
		}

		public void setValue(String value) {
			this.value = value;
		}

		@Override
		public String toString() {
			return " " + key +" "+ value; 
		}

		public String getFlag() {
			return flag;
		}

		public void setFlag(String flag) {
			this.flag = flag;
		}

		public String getKey() {
			return key;
		}

		public void setKey(String key) {
			this.key = key;
		}

		public String getContent() {
			return content;
		}

		public void setContent(String content) {
			this.content = content;
		}

		private String flag = "";
		private String key ="";
		private String value ="";
		private String content = "";
		
		

		public TextPair(String flag, String key, String value, String content) {
			this.flag = flag;
			this.key = key;
			this.value = value;
			this.content = content;
		}

		public TextPair() {
		}

		@Override
		public void write(DataOutput out) throws IOException {
			// TODO Auto-generated method stub
			out.writeUTF(this.flag);
			out.writeUTF(this.key);
			out.writeUTF(this.value);
			out.writeUTF(this.content);
		}

		@Override
		public void readFields(DataInput in) throws IOException {
			// TODO Auto-generated method stub
			this.flag = in.readUTF();
			this.key = in.readUTF();
			this.value = in.readUTF();
			this.content = in.readUTF();
		}

		@Override
		public int compareTo(TextPair o) {
			// TODO Auto-generated method stub
			return 0;
		}
		
		
	}
	
	
	

}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MapReduce 中进行单连接join)需要使用到 Map 和 Reduce 两个阶段,具体步骤如下: 1. 将两个连接按照连接字段进行排序和分区,保证相同连接字段值的记录在同一个分区中。 2. 在 Map 阶段,对于每个分区中的记录,将连接字段作为输出的 key,将记录作为输出的 value,然后将它们发送到 Reduce 阶段进行处理。其中,对于第一个的记录,需要在 value 中添加一个标记以区分不同的记录。 3. 在 Reduce 阶段,对于每个连接字段相同的记录,将它们进行组合,生成连接后的记录。具体步骤如下: a. 对于每个连接字段相同的记录,将它们分别存储到两个缓存中,一个缓存存储第一个的记录,另一个缓存存储第二个的记录。 b. 对于每个第一个的记录,将它与第二个的缓存中相同连接字段的记录进行组合,生成连接后的记录。如果第二个的缓存中没有相同连接字段的记录,则不生成连接记录。 4. 将连接后的记录按照连接字段排序,输出最终结果。 需要注意的是,在 MapReduce 中进行单连接操作会产生大量的中间结果,因此需要进行合理的优化和调整,以提高性能和减少资源消耗。例如,可以使用 Combiner 函数来对 Map 阶段的输出进行局部聚合,减少数据传输量和 Reduce 阶段的计算量。同时,也可以对进行预处理和缓存,以减少数据量和加快处理速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值