MapReduce编程实例-----词频统计(浅记)

本文详细介绍了在Windows环境下,如何使用MapReduce进行词频统计的完整过程,包括Map、Reduce和Driver阶段的实现,以及可能出现的异常及解决方法。读者将学习到如何自定义Mapper和Reducer,以及如何处理和输出数据。

实验目的:
        Windows系统下,通过MapReduce实现次词频统计

MapReduce编程实例-----词频统计

1)·首先,MapReduce通过默认组件TextInputFormat将待处理的数据文件(如ext1.txt和text2.txt),
把每一行的数据都转变为<key,value>键值对;
2)·其次,调用Map()方法,将单词进行切割并进行计数,输出键值对作为Reducer阶段的输入键值对
3)·最后,调用Reduce()方法将单词汇总、排序后,通过TextOutputFormat组件输出结果文件中

Map阶段:

1)自定义Mapper,继承自己的父类;
2)Mapper输入数据是kv键值对形式;形如<a,1> <b,2>
3)Mapper阶段的逻辑代码写入map()方法内;
4)Mapper输出的数据也是kv键值对类型;
5)map()方法,每一个kv都要调用一次;

package word.com;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

/*
 *Mapper<KEYIN, VALUEIN, KEYOUT, VALUEOUT>
 *KEYIN:表示mapper阶段数据输入时key的数据类型,读一行数据,返回一行给MR程序
 *这种情况下KEYIN表示每一行的起始偏移量,因此数据类型为Long
 *VALUEIN: 表示mapper阶段数据输入时Value的数据类型,在默认读取数据组件下,VALUEIN表示读取的一行内容,因此为String
 *KEYOUT:表示mapper阶段数据输出时key的数据类型,本案例中输出的Key是单词,因此用String
 *VALUEOUT:表示mapper阶段数据输出是Value的数据类型,本案例中输出值Value为单词出现的次数,因此用Integer
 *使用Hadoop特殊的序列化类型:long -- LongWritable, String -- Text, Integer -- InWritable
 * */
public class WordMapper extends Mapper<LongWritable, Text, Text, IntWritable>{

	@Override
	protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, IntWritable>.Context context)
			throws IOException, InterruptedException {
		String line = value.toString();
		String[] words = line.split(" ");
		for(String word:words){
			context.write(new Text(word), new IntWritable(1));
		}
		
	}



}

 Reduce阶段:

1)自定义Reducer,继承自己的父类;
2)Reducer输入数据是mapper的输出数据类型;形如<a,1> <b,2>
3)Reducer阶段的逻辑代码写入reducer()方法内;
4)reducer()方法,每一个相同的kv都要调用一次;

package word.com;

import java.io.IOException;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
/*
 * 这里是MR程序reducer阶段处理的类
 * KEYIN:这是Reducer阶段数据输入key的数据类型,对应Mapper阶段输出key的类型
 * VALUEIN:这是Reducer阶段数据输入value的数据类型,对应Mapper阶段输出value的类型
 * KEYOUT:这是Reducer阶段输出key的数据类型,本案例中,是Text
 * VALUEOUT:这是Reducer阶段输出value的数据类型,本案例中,是IntWritable
 * 
 * **/

public class WordReduce extends Reducer<Text, IntWritable, Text, IntWritable>{

	@Override
	protected void reduce(Text key, Iterable<IntWritable> values,
			Reducer<Text, IntWritable, Text, IntWritable>.Context context) throws IOException, InterruptedException {
		int count = 0;
		for(IntWritable value:values){
			count += value.get();
		}
		context.write(key, new IntWritable(count));
	}
	
}

 Driver阶段:

 通俗讲,相当于连接Mapper和Reducer的桥梁

package word.com;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

public class WordDriver {

	public static void main(String[] args) throws Exception {
		// 1. 获取 job
		Configuration conf = new Configuration();
//		conf.set("fs.defaultFS", "hdfs://192.168.170.133:9000");
		 //2.加载jar驱动
		Job job = Job.getInstance(conf);
		job.setJarByClass(WordDriver.class);
		 // 3. 关联 mapper 和 reducer
		job.setMapperClass(WordMapper.class);
		job.setReducerClass(WordReduce.class);
		 // 4. 设置 map 输出的 k v 类型
		job.setMapOutputKeyClass(Text.class);
		job.setMapOutputValueClass(IntWritable.class);
		 // 5. 设置最终输出的k v类型
		job.setOutputKeyClass(Text.class);
		job.setOutputValueClass(IntWritable.class);
		 // 6. 设置输入路径和输出路径
		FileInputFormat.addInputPath(job, new Path("F:\\input\\test1.txt"));
		FileOutputFormat.setOutputPath(job, new Path("F:\\output"));//output之前是不存在的
		 // 7. 提交 job
		job.submit(); //提交的yarn
		boolean b = job.waitForCompletion(true);
		System.out.println(b?"成功":"失败");
	}

}

实验结果:

 可能出现的问题

        Windows系统下运行代码,可能会出现Exception in thread "main"            java.lang.NullPointerException

解决方法

        将hadoop.dll放到C:\Windows\System32(之前放到hadoop-2.7.2\bin没起作用😓)

        将winutils.exe放到hadoop-2.7.2\bin下就可(不要忘记事先配好环境变量)

### MapReduce初级编程实战实验五教程 #### 实验目标 本实验旨在帮助学习者掌握基本的MapReduce编程方法以及如何利用MapReduce解决实际的数据处理问题,例如数据去重、数据排序和简单的数据分析等[^1]。 #### 实验环境准备 为了顺利完成此实验,需搭建如下开发环境: - **操作系统**: Linux (推荐 Ubuntu 16.04) - **Hadoop 版本**: Hadoop 2.7.1 确保已安装并配置好Java运行环境(JDK),同时完成Hadoop集群或单机模式的部署与测试[^1]。 #### 编程实践内容概述 以下是基于MapReduce框架实现常见功能的具体描述: ##### 数据去重 在某些场景下可能需要去除重复录。可以通过设计Mapper阶段仅输出键值对而不改变输入顺序,在Reducer中判断相同Key对应的第一个Value即可视为唯一项。 ##### 数据排序 当面对大量无序数据集时,可以借助于MapReduce天然支持的Shuffle过程来自动完成全局范围内的按键升序排列工作流。如果希望自定义比较逻辑,则可以在Job设置里指定Comparator类。 ##### 温度统计分析(以年度最高最低气温为例) 假设有一组气象观测站多年来的每日平均温度录文件作为源数据。每条录由日期字符串与对应整数型温度组成。下面介绍一种简单的方法用于计算各年的最大最小温差情况: ###### Mapper部分伪代码展示 ```java public class TempMapper extends Mapper<LongWritable, Text, IntWritable, IntWritable> { private final static IntWritable year = new IntWritable(); private final static IntWritable temp = new IntWritable(); @Override protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException { String[] tokens = value.toString().split(","); int currentYear = Integer.parseInt(tokens[0].substring(0,4)); // 提取年份 int temperature = Integer.parseInt(tokens[1]); // 获取温度 year.set(currentYear); temp.set(temperature); context.write(year,temp); // 输出<year,temperature> } } ``` ###### Reducer部分说明 由于来自同一key的所有values会被传递给同一个reducer实例处理,所以这里可以直接遍历迭代器找出其中的最大值和最小值[^2]: ```java public class TempReducer extends Reducer<IntWritable, IntWritable, NullWritable, Text> { @Override protected void reduce(IntWritable key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { Iterator<IntWritable> iterator = values.iterator(); if (!iterator.hasNext()) return; int minTemp = iterator.next().get(); // 初始化min/max为首个元素 int maxTemp = minTemp; while(iterator.hasNext()){ int nextVal = iterator.next().get(); if(nextVal < minTemp){ minTemp = nextVal; }else if(nextVal > maxTemp){ maxTemp = nextVal; } } StringBuilder resultBuilder = new StringBuilder(); resultBuilder.append("Year=").append(key.get()) .append(", Min Temperature=").append(minTemp) .append(", Max Temperature=").append(maxTemp); context.write(NullWritable.get(),new Text(resultBuilder.toString())); } } ``` #### 操作步骤概览 按照以下流程执行整个项目构建到最终验证的过程: 1. 创建一个新的Eclipse Java Project或者IDEA Maven Module; 2. 添加必要的依赖库(hadoop-core.jar及其他关联组件); 3. 定义自己的Mapper&Reducer子类继承默认接口,并覆盖相应函数体; 4. 构建Driver程序负责组装job参数提交至远程YARN资源管理器调度运行; 5. 准备模拟的小规模样本txt文档上传hdfs分布式存储系统路径下供本地调试用途; 6. 执行编译打包命令生成jar包形式分发节点间加载调用; 7. 查看控制台日志确认作业状态直至成功结束为止最后下载结果查看准确性[^1].
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值