title: 实验一mapreduce编程运用1
date: 2023-10-10 13:35:49
categories:
- mapreduce
tags:
目录
环境介绍
- Linux: Ubuntu 16.04 LTS
- hadoop2.7
. 前提准备工作
-
开始
1.1 准备数据集
- YoutubeDataSets.txt 把数据集放在/usr/local/hadoop/mydata路径下,如果是放在Downlocads目录下可以使用终端命令
```bash
hadoop@ubuntu:~$ mv /home/hadoop/Downloads/YoutubeDataSets.txt /usr/local/hadoop/mydata/
1.2 准备好java环境 - 创建项目:可以按照教程:https://dblab.xmu.edu.cn/blog/2460/ > **注意:** 一定要导入的jar包有: - 1.“/usr/local/hadoop/share/hadoop/common”目录下的所有JAR包,包括hadoop-common-3.1.3.jar、hadoop-common-3.1.3-tests.jar、haoop-nfs-3.1.3.jar和haoop-kms-3.1.3.jar,注意,不包括目录jdiff、lib、sources和webapps; - 2.“/usr/local/hadoop/share/hadoop/common/lib”目录下的所有JAR包; - 3.“/usr/local/hadoop/share/hadoop/hdfs”目录下的所有JAR包,注意,不包括目录jdiff、lib、sources和webapps; - 4.“/usr/local/hadoop/share/hadoop/hdfs/lib”目录下的所有JAR包; - 5.“/usr/local/hadoop/share/hadoop/yarn”目录下的所有JAR包,注意,不包括目录lib、sources和test; - 6.“/usr/local/hadoop/share/hadoop/yarn/lib”目录下的所有JAR包; - 7.“/usr/local/hadoop/share/hadoop/mapreduce”目录下的所有JAR包,注意,不包括目录lib、lib-example和sources; - 8.“/usr/local/hadoop/share/hadoop/mapreduce/lib”目录下的所有JAR包。 1.3 启动hadoop,清理以前input和output里面的文件(可选,因为你可以指定hdfs其他目录) ```bash (base) hadoop@ubuntu:~$ cd /usr/local/hadoop
(base) hadoop@ubuntu:/usr/local/hadoop$ ./sbin/start-dfs.sh
(base) hadoop@ubuntu:/usr/local/hadoop$ ./bin/hdfs dfs -rm -r input
(base) hadoop@ubuntu:/usr/local/hadoop$ ./bin/hdfs dfs -rm -r output
解决问题
注意: 开始解决问题
- 解决第一道题目,得出youtube每一个up主的id次数,并且按照降序排序
1.1 导入代码如图:
1.2 分别运行代码:TopListProcess.java,ToListSort.java,得到class文件,然后导出成jar包到/usr/local/hadoop/myapp/路劲下,如图
1.3 运行:
-
导入数据集到hdfs里面的input目录下
(base) hadoop@ubuntu:/usr/local/hadoop$ ./bin/hdfs dfs -put ./mydata/YoutubeDataSets.txt input
-
运行TolistProcess.jar包
注意: input和output是指定的输入输出目录
bash (base) hadoop@ubuntu:/usr/local/hadoop$ ./bin/hadoop jar ./myapp/TolistProcess.jar input output
运行如图:
- 运行ToplistSort.jar包
注意: output和output2是指定的输入输出目录
bash (base) hadoop@ubuntu:/usr/local/hadoop$ ./bin/hadoop jar ./myapp/ToplistSort.jar output output2
运行如图:
-
解决实训4-1题目1
2-1. 题目
- 在 Mapper 类中,map 函数读取成绩表A 中的数据,直接将读取的数据以空格(参考书籍配套资源中的格式)
分隔,组成键值对<科目,成绩>,即设置输出键值对类型为<Text,INtWritable> (2)在 Reducer 中,由于 map 函数输出键值对类型是<Text,IntWritable>,所以 Reducer接收的键值对是<Text,Iterable>针对相同的键(即科目)遍历比较他的值(即成绩),找出最高值(最高成绩),最后输出键值对<科目,最高成绩>。
2-2. 数据处理
注意: 这一步一定要做
- 把数据集格式改成utf-8(如果虚拟机用ANSI可以就不用改)
- 不改后面运行可能出现报错哦
2-3. 解决
- 使用eclipse控制台指定输入输出目录
- 操作
- 创建包tonji
- 创建类ScoreAnalyzer
- 代码(直接指定目录输入输出):
> **注意:** 输出路劲不能创建好,否则会报错
package tonji;
- 在 Mapper 类中,map 函数读取成绩表A 中的数据,直接将读取的数据以空格(参考书籍配套资源中的格式)
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class ScoreAnalyzer {
public static class ScoreMapper extends Mapper<Object, Text, Text, IntWritable> {
private Text subject = new Text();
private IntWritable score = new IntWritable();
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
// 按空格分隔成绩数据,前一部分为科目,后一部分为成绩
String[] parts = value.toString().split(" ");
if (parts.length == 2) {
subject.set(parts[0]);
score.set(Integer.parseInt(parts[1]));
context.write(subject, score);
}
}
}
public static class ScoreReducer extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context)
throws IOException, InterruptedException {
int maxScore = Integer.MIN_VALUE;
for (IntWritable val : values) {
maxScore = Math.max(maxScore, val.get());
}
result.set(maxScore);
context.write(key, result);
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
conf.set(“fs.defaultFS”,“hdfs://localhost:9000”);
String[] args1 = new String[] { “input”, “outputscore” }; /* 直接设置输入参数 input是输入路劲,outputscore是输出路劲*/
Job job = Job.getInstance(conf, "Score Analyzer");
job.setJarByClass(ScoreAnalyzer.class);
job.setMapperClass(ScoreMapper.class);
job.setReducerClass(ScoreReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(args1[0]));
FileOutputFormat.setOutputPath(job, new Path(args1[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
- 代码解释
Mapper类(ScoreMapper):
ScoreMapper 是MapReduce作业的Mapper阶段的自定义类。它继承了Mapper类,用于处理输入数据,并将其映射为键值对。map
方法是Mapper类中的主要方法。它负责将输入数据行解析为键值对,其中键是科目(Text类型),
值是成绩(IntWritable类型)。每行输入数据都会被拆分为两部分,使用空格分隔。
第一部分是科目,第二部分是成绩。这些数据将被映射为键值对,并传递给Reducer阶段。
Reducer类(ScoreReducer):
ScoreReducer 是MapReduce作业的Reducer阶段的自定义类。它继承了Reducer类,用于对Mapper阶段输出的键值对
进行汇总和处理。 reduce 方法是Reducer类中的主要方法。它接收一组具有相同键(科目)的键值对,
这些键值对来自Mapper阶段的输出。 在reduce 方法中,它迭代所有成绩值,找到最高成绩,并将最高成绩与相应的科目一起写出。
main方法:
main 方法是整个MapReduce作业的入口点。它配置作业,设置输入和输出路径,并启动作业的执行。
作业配置包括指定Mapper和Reducer类,以及设置键和值的数据类型。
输入路径和输出路径通过命令行参数传递给作业。
总结:这段代码的主要目标是将成绩数据进行分析,找到每个科目的最高成绩,并将结果写入到输出文件中。这是一个典 型的MapReduce任务,其中Mapper阶段负责数据解析和映射,而Reducer阶段负责聚合和计算。最终的结果是每个科目的最高成绩。
2-3.运行截图
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=90D8FA25F260AE5EBDFF0F08EEA6D95C976455E2262BD20513BAAB7160B4802E0722E9ABAA4CBAEAB1C07FB305DB441E8FD2AF8D916B51066E873C1F8307FF3971FD8FC2BC41EAB04945B10803150AA828DB92A02949319ADF6BE5A84291EF2D526A36AC5B796D5B25F390CC0B690ED7">
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=F542F798ED6A05E4F69F2FBEFE2DB656EDFC212BC1C7E8737B026704DE2DD24A99AD74C9DDB55432FE8749B2C0E0E5342CA201CCFBF4A211EB8737EBBAE4A3BB7258FF3C3FAE84EB743893CFE710CB64056691FC8ED4E168C80AF09E5BBA4B5379DB2A398308844FB84282A4E47116DE">
3. 解决实训4-1题目2
3-1. 统计对应日期的访问次数
3-2. 解决
- 操作
1. 创建包dataCount
2. 导入给好的类dailyAccessCount.java和accessTimesSort.java
3. 先运行,后一个一个导出到/usr/local/hadoop/myapp下accessCount.jar和accessTimesSort.jar
4. 删除hdfs上的input和output目录,又创建回来,导入日期user_login.txt数据集到input目录下
5. 根据下图执行代码,先count后sort,升序排序
- 操作图:
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=4CD7D050BAEC0E6B8D6BA70863A843B279F3F6C584F6B28FEEDD326B1EAF8E69B70DE090165B88D58376D709C197DF11115C3B173F37943992E02B96882EF6327BCBF15529CFBAEFE9E914332A41BD0CD445EBACAF6D87C1337E85CAD950EEA61233269091F7524372DB01C70B4CB1FD">
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=4A0D625FB9866626665C105EB41CFE3143B0D0205F7C1623A881DD02FD981EC33A9AD5D942C83F007CEE812B903A79B53CD5BAAFFBEB7E7A4F2DDC42834D09D95942C5C43E8C81E98621F7C83E1843372E5C0328AB208EB12000C0CBA7488509C146DA47CFCC409B5230B76B8BB98A86">
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=0BAE19AF83E3BA18AEF9BBC3E01CCC1AFCCE8321C6AEA3CC7B161D9594178C3B7AB24FB506ECE8E310F073315DD30DF0097F9F99F8591318EDDB4DBEEC998B890DB38F36551A3AE64D4E13617274C43F2466894BDBDCCE0AFD14D478BEF8AB558CF1B63205CAAC023ACF96A34BABFAD9">
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=4721CE8EA2BD0837C9E231E1FE992B51B3055A77241451CEE63D6877FF5B0811959EC5B660046CBD49F151989B9A34C3A39310B47FBD6B16CEFF87BC8BEE1ACE10BD520B94968B48E1938E042FDDD2DECBDF63889CEFBF9A6EFB4AD408DE4D8747DADAA35848D93B0373FF33A3C787D1">
<img class="fit-picture"
src="https://preview.cloud.189.cn/image/imageAction?param=9D6141714E7221F42170DC6DC4D9A5B297FB4079EB7D5A43617C9914ED586D1736DF177ED5844285BA6F8EBAF0094435F5AC5AE02805F2ACC6C5FB1B29383B11B2496EFE14E907B6BF9052495144B5C457A89418A18E64E87885E5FFF862BF26512A99C9AF08338C8498D03E3E25ED56">
4. 解决实训4-1题目3
4-1. 题目:合并两个文件相同的内容,XX与YY,可以参照林子雨老师的大数据基础编程后面实验五第一题
4-2. 解决
- 使用eclipse控制台指定输入输出目录
- 操作
1. 创建包hebing
2. 创建类combine
- 代码(直接指定目录输入输出):
> **注意:** 输出路劲不能创建好,否则会报错
```java
package hebing;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
public class combine {
/**
* 对 A, B 两个文件进行合并,并剔除其中重复的内容,得到一个新的输出文件 C
*/
// 重载 map 函数,直接将输入中的 value 复制到输出数据的 key 上
public static class Map extends Mapper<Object, Text, Text, Text> {
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<Text, Text, Text, Text> {
public void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
context.write(key, new Text(""));
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
conf.set("fs.defaultFS","hdfs://localhost:9000");
String[] otherArgs = new String[] { "XXYY", "output" }; /* XXYY是输入路劲,output是输出路劲 */
if (otherArgs.length != 2) {
System.err.println("Usage: wordcount <in><out>");
System.exit(2);
}
Job job = Job.getInstance(conf, "Merge and duplicate removal");
job.setJarByClass(combine.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);
}
}
4-3. 最终结果: