Hadoop:MapReduce之倒排索引
- 前言
- 一、案例要求
- 二、實作程序
- 1.IntelliJ IDEA 創建Maven工程
- 2.完整代碼
- 3.Maven打包
- 4.Hadoop集群運行
- 推薦Hadoop學習視頻
前言
本案例有一定門檻,需要一點Java基礎,Hadoop入門級知識,涉及Maven管理,pom組態檔,Maven打包,Linux虛擬機的使用,Hadoop集群,若閱讀期間感覺吃力請自行補課,當然有疑問,也歡迎評論留意或私信我,
一、案例要求
1) 實作倒排索引效果:統計每個單詞在不同檔案中的出現次數;查看下方的案例說明;
2) 輸入:自己編輯幾個檔案,例如 a.txt,b.txt,c.txt,
每個檔案的內容為若干行單詞,單詞之間以空格分開,
并將這些檔案上傳到 hdfs 的/reversed 目錄下;例如a.txt的內容:
hadoop google scau
map hadoop reduce
hive hello hbase
3) 撰寫程式實作單詞的倒排索引效果;
4) 磁區要求:以 A-M 字母開頭(包含小寫)的單詞出現
在 0 區;以 N-Z 字母開頭的單詞出現在 1 區;其余開
頭的單詞出現在 2 區;
5) 單詞的輸出形式:hadoop a.txt->2,b.txt->1,其中
hadoop 是單詞(也作為輸出的 key),”
a.txt->2,b.txt->1”表示輸出的 value,即表示
hadoop 單詞在 a.txt 檔案中出現次數為 2,在 b.txt
檔案中出現次數為 1;
案例說明:
第一次 MapReduce,統計各檔案中不同單詞的出現次數;SCAU
輸出結果(K,V)的形式示例(可以自定義,默認以\t 分
隔)如下:
hadoop->a.txt 2
hadoop->b.txt 1
map->a.txt 1
map->b.txt 1
第二次 MapReduce,將以上結果(路徑)作為輸入,處理后
輸出倒排索引;
輸出結果(K,V)的形式為:
hadoop a.txt->2,b.txt->1
map a.txt->1,b.txt->1
其他:根據 context 獲取檔案名:
FileSplit inputSplit = (FileSplit)
context.getInputSplit();
Path path = inputSplit.getPath();
String filename = path.getName();
二、實作程序
1.IntelliJ IDEA 創建Maven工程
專案層次結構如圖:

2.完整代碼
ReversedMapper.java
package reversedindex;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import java.io.IOException;
public class ReversedMapper extends Mapper<LongWritable, Text,Text,Text> {
private Text outKey = new Text();
private Text outValue = new Text("1");
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
FileSplit inputSplit = (FileSplit)context.getInputSplit();
String fileName = inputSplit.getPath().getName();
String[] words = value.toString().split(" ");
for (String word : words) {
outKey.set(word+"->"+fileName);
context.write(outKey,outValue);
}
}
}
ReversedCombiner.java
package reversedindex;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class ReversedCombiner extends Reducer<Text,Text,Text, Text> {
private Text outKey = new Text();
private Text outValue = new Text();
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
int count = 0;
for (Text value : values) {
count+=Integer.parseInt(value.toString());
}
String[] words = key.toString().split("->");
outKey.set(words[0]);
outValue.set(words[1]+"->"+count);
context.write(outKey,outValue);
}
}
ReversedPartitioner.java
package reversedindex;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
public class ReversedPartitioner extends Partitioner<Text,Text> {
@Override
public int getPartition(Text text, Text text2, int i) {
char head = Character.toLowerCase(text.toString().charAt(0));
if(head>='a'&& head<='m')
return 0;
else if(head>'m'&& head<='z')
return 1;
else
return 2;
}
}
ReversedReducer.java
package reversedindex;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
import java.io.IOException;
public class ReversedReducer extends Reducer<Text,Text, Text,Text> {
private Text outValue = new Text();
@Override
protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
StringBuilder stringBuilder = new StringBuilder();
for (Text value : values) {
stringBuilder.append(value.toString()).append(",");
}
String outStr = stringBuilder.substring(0,stringBuilder.length()-1);
outValue.set(outStr);
context.write(key,outValue);
}
}
ReversedIndex.java
package reversedindex;
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.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class ReversedIndex{
public static void main(String[] args) throws Exception {
Job job = Job.getInstance(new Configuration());
job.setJarByClass(ReversedIndex.class);
job.setMapperClass(ReversedMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(Text.class);
job.setReducerClass(ReversedReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
job.setCombinerClass(ReversedCombiner.class);
job.setPartitionerClass(ReversedPartitioner.class);
job.setNumReduceTasks(3);
FileInputFormat.setInputPaths(job,args[0]);
FileOutputFormat.setOutputPath(job,new Path(args[1]));
boolean result = job.waitForCompletion(true);
System.exit(result?0:1);
}
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>MapReduceExp3</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<hadoop.version>3.1.3</hadoop.version>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.Maven打包

如圖所示,在右側點擊Maven的package進行打包,打包結果會在左側的target檔案夾中輸出,最終需要的只是標紅的Jar包,
4.Hadoop集群運行
前序的配置步驟此處跳過,將本地Jar包發送到主節點主機自選的檔案夾,然后開啟start-dfs.sh和start-yarn.sh開啟hdfs和yarn集群,在hdfs里新建reversed檔案夾,通過瀏覽器localhost:9870打開hdfs可視化網頁,竟然檔案夾管理上傳a.txt,b.txt等到reversed檔案夾里,
主節點主機上執行:hadoop jar 指定jar包 專案java目錄開始的主類路徑 /reversed 不存在的輸出檔案夾
本案例指令供參考對照 :
hadoop jar MapReduceExp3-1.0-SNAPSHOT.jar reversedindex.ReversedIndex /reversed /reversed_out

運行完畢后可在hdfs可視化頁面查看reversed_out檔案夾中的結果,
推薦Hadoop學習視頻
黑馬的課程,親測很不錯:https://www.bilibili.com/video/BV1JT4y1g7nM
解決本案例的視頻講解,適合快速入門:
Hadoop之MapReduce實戰-倒排索引(上)https://www.bilibili.com/video/BV1Vt411v7jH
MapReduce實戰-倒排索引(下):https://www.bilibili.com/video/BV1Lt411v7nZ
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/276736.html
標籤:其他
