Mapreduce 计算TF

最近在学习mapreduce编程方面的知识,刚开始学习,所以障碍感觉还是有很多的。有不少地方不明白,看来还是要好好的看一下mapreduce的实现机制,以及提供的函数接口的功能是什么。

package an.hadoop.tf;

//计算文件的TF值 
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
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.Partitioner;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.Mapper.Context;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;




public class ComputeTF {

	public static class Mapper_TF extends Mapper <LongWritable, Text, Text , Text>{
		String file_name ="";
		int word_count = 0;
		static Text one = new Text("1");
		String word;
		//每个map也只是一个文件吗?其实是在执行循环,就是循环的在执行这个map 而不是一次调用
		//file-name 和word-count 都能作为对一个文件的全局量,所以应该是每个文件都会初始化一次file-name
		//也对,任务是分配到不同的map上执行的,也就说会调用多次map来做
		public void map(LongWritable key, Text value, Context context)
				throws IOException, InterruptedException {
			//这个分裂输入
			FileSplit split = (FileSplit) context.getInputSplit();
			//split应该输入文件
			String str = split.getPath().toString();
			file_name = str.substring(str.lastIndexOf("/")+1); //获取文件名
			//分词
			StringTokenizer itr = new StringTokenizer(value.toString());
			while (itr.hasMoreTokens()) {
				word = file_name ;
				word += " ";
				word += itr.nextToken();  //将文件名加单词作为key es: test1 hello  1
				word_count++;
				context.write(new Text(word), one);
			}
			
		}//map
		
		public void cleanup(Context context) throws IOException,
		InterruptedException {
			//Map的最后,我们将单词的总数写入。下面需要用总单词数来计算。
			String str = "";
			str += word_count;
			context.write(new Text(file_name + " " + "!"), new Text(str));
			//主要这里值使用的 "!"是特别构造的。 因为!的ascii比所有的字母都小。
		}
		
	}//mapper
	
	public static class Reduce_TF extends Reducer<Text, Text, Text, Text> {
		float all = 0;
		public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
			int index = key.toString().indexOf(" ");
			//因为!的ascii最小,所以在map阶段的排序后,!会出现在第一个
			if (key.toString().substring(index + 1, index + 2).equals("!")){
			for (Text val : values) {
					//获取总的单词数。
					all = Integer.parseInt(val.toString());
				}
				//这个key-value被抛弃
				return;
			}
			float sum = 0;  //统计某个单词出现的次数
			for (Text val : values) {
				sum += Integer.parseInt(val.toString());
			}
			//跳出循环后,某个单词数出现的次数就统计完了,所有 TF(词频) = sum / all
			float tmp = sum / all;
			String value = "";
			value += tmp;  //记录词频
			
			//将key中单词和文件名进行互换。es: test1 hello -> hello test1
			String p[] = key.toString().split(" ");
			String key_to = "";
			
			key_to += p[1];
			key_to += " ";
			key_to += p[0];
			
			context.write(new Text(key_to), new Text(value));
		}
	}//reducer
	//一定要加上这个reduce才行,也不是太明白为什么
	public static class Reduce_Part1 extends Reducer<Text, Text, Text, Text> {
		
		public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
			for (Text val : values) {
				
				context.write(key, val);
			}
		}
	}
	
	
	public static void main(String[] args) throws Exception {
			
		Configuration conf = new Configuration();
	    String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
	    if (otherArgs.length != 2) {
	      System.err.println("Usage: TF-IDF <in> <out>");
	      System.exit(2);
	    }
	    int file_number = 5;
	    
	    Job job = new Job(conf, "comute tf-idf");
	    //设置对应的主类,map、reduce和combine类
	    job.setJarByClass(ComputeTF.class);
	    job.setMapperClass(Mapper_TF.class);
	    job.setCombinerClass(Reduce_TF.class);
	    job.setReducerClass(Reduce_Part1.class);
	    //mapreduce的输出数据格式
	    job.setMapOutputKeyClass(Text.class);
	    job.setMapOutputValueClass(Text.class);
	    job.setOutputKeyClass(Text.class);
	    job.setOutputValueClass(Text.class);
	    
	    //job.setPartitionerClass(MyPartitoner.class); //使用自定义MyPartitoner
	    //输入输出路径设置
	    FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
	    FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
	    System.exit(job.waitForCompletion(true) ? 0 : 1);
	}
	
}//compute-tf


希望各位能够多多指点,以及给推荐一下需要学习的资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值