大數據hadoop學習【13】-----通過JAVA編程實現對MapReduce的數據進行排序目錄
上次的博客中,林君學長通過java編程實現了對MapReduce的數據去重;本次博客,我們將深入瞭解MapReduce,並通過java編程實現對文件數據中數據的排序,一起看步驟吧!
- 本次排序要求: 對輸入文件中數據進行排序。輸入文件中的每行內容均爲一個數字,即一個數據。要求在輸出中每行有兩個間隔的數字,其中,第一個代表原始數據在原始數據集中的位次,第二個代表原始數據。
一、數據準備
1、ubuntu文件系統中準備對應數據文件
1)、在對應位置創建file3.txt文件,並寫入相關數據:文件中的每行都是一個數據
(1)、創建file3.txt文件,並打開
cd ~/lenovo/data
touch file3.txt
gedit file3.txt
其中 ~/lenovo/data爲林君自己創建的文件夾
(2)、寫入文件內容如下所示:
2
32
654
32
15
756
65223
2)、在相同位置創建file4.txt文件,並寫入數據,兩個文件中的數據應該要有相同的和不同的,且文件中的每行都是一個數據
(1)、創建file4.txt文件,並打開
touch file4.txt
gedit file4.txt
(2)、寫入文件內容如下所示:
5956
22
650
92
3)、在相同位置創建file5.txt文件,並寫入數據,兩個文件中的數據應該要有相同的和不同的,且文件中的每行都是一個數據
(1)、創建file5.txt文件,並打開
touch file5.txt
gedit file5.txt
(2)、寫入文件內容如下所示:
26
54
6
2、運行hadoop
1)、終端輸入以下命令運行hadoop
start-dfs.sh
2)、查看hadoop是否成功運行
jps
出現以上4個節點則爲成功運行!
3、將文件上傳至hadoop文件系統
1)、在hdfs文件系統中創建file2目錄用來存放我們上傳的文件
hdfs dfs -mkdir /user/hadoop/file2
2)、將file3.txt文件上傳至hdfs文件系統中的file2目錄
hdfs dfs -put ~/lenovo/data/file3.txt /user/hadoop/file2
3)、將file4.txt文件上傳至hdfs文件系統中的file2目錄
hdfs dfs -put ~/lenovo/data/file4.txt /user/hadoop/file2
4)、將file5.txt文件上傳至hdfs文件系統中的file2目錄
hdfs dfs -put ~/lenovo/data/file5.txt /user/hadoop/file2
5)、查看文件是否上傳成功
hdfs dfs -ls /user/hadoop/file2
6)、查看文件內容是否一致
hdfs dfs -cat /user/hadoop/file2/file3.txt
hdfs dfs -cat /user/hadoop/file2/file4.txt
hdfs dfs -cat /user/hadoop/file2/file5.txt
二、編寫java程序
1、打開eclipse,編寫數據排序的java代碼
1)、新建類Sort ,其中java代碼如下所示:
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.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 java.io.IOException;
/**
* 數字排序
*/
public class Sort{
/**
* 使用Mapper將數據文件中的數據本身作爲Mapper輸出的key直接輸出
*/
public static class forSortedMapper extends Mapper<Object, Text, IntWritable, IntWritable> {
private IntWritable mapperValue = new IntWritable(); //存放key的值
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString(); //獲取讀取的值,轉化爲String
mapperValue.set(Integer.parseInt(line)); //將String轉化爲Int類型
context.write(mapperValue,new IntWritable(1)); //將每一條記錄標記爲(key,value) key--數字 value--出現的次數
//每出現一次就標記爲(number,1)
}
}
/**
* 使用Reducer將輸入的key本身作爲key直接輸出
*/
public static class forSortedReducer extends Reducer<IntWritable, IntWritable, IntWritable, IntWritable>{
private IntWritable postion = new IntWritable(1); //存放名次
@SuppressWarnings("unused")
@Override
protected void reduce(IntWritable key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
for (IntWritable item :values){ //同一個數字可能出多次,就要多次並列排序
context.write(postion,key); //寫入名次和具體數字
System.out.println(postion + "\t"+ key);
postion = new IntWritable(postion.get()+1); //名次加1
}
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration(); //設置MapReduce的配置
String[] otherArgs = new GenericOptionsParser(conf,args).getRemainingArgs();
if(otherArgs.length < 2){
System.out.println("Usage: Sort <in> [<in>...] <out>");
System.exit(2);
}
//設置作業
//Job job = new Job(conf);
Job job = Job.getInstance(conf);
job.setJarByClass(Sort.class);
job.setJobName("SortedData");
//設置處理map,reduce的類
job.setMapperClass(forSortedMapper.class);
job.setReducerClass(forSortedReducer.class);
//設置輸入輸出格式的處理
job.setOutputKeyClass(IntWritable.class);
job.setOutputValueClass(IntWritable.class);
//設定輸入輸出路徑
for (int i = 0; i < otherArgs.length-1;++i){
FileInputFormat.addInputPath(job,new Path(otherArgs[i]));
}
FileOutputFormat.setOutputPath(job, new Path(otherArgs[otherArgs.length-1]));
System.exit(job.waitForCompletion(true)?0:1);
}
}
在MapReduce流程中,Map的輸出<Key,value>經過shuffle過程聚集成<key,value-list>後會被交給Reduce。所以從設計好的Reduce輸入可以反推出Map的輸出的Key應爲數據,而value爲任意值。繼續反推,Map輸出的Key爲數據。而在這個實例中每個數據代表輸入文件中的一行內容,所以Map階段要完成的任務就是在採用Haodoop默認的作業輸入方式之後,將value設置成Key,並直接輸出(輸出中的value任意)。Map中的結果經過shuffle過程之後被交給reduce。在Reduce階段不管每個Key有多少個value,都直接將輸入的Key複製爲輸出的Key,並輸出就可以了(輸出中的value被設置成空)
2)、運行,測試代碼沒有問題
控制檯出現如上顯示則代碼沒有問題!
2、將java文件打包成jar
1)、按照如下截圖步驟鏡像jar打包
2)、選擇JAR file
3)、選擇導出的類和導出路徑
4)、點擊ok
5)、導出成功
出現finished則爲導出成功!
6)、找到對應路徑,查詢該包是否成功導出
出現以上箭頭的jar包,則導出成功,然後關閉eclipse
三、結果測試
1、終端運行jar包
1)、終端輸入如下命令運行我們導出的jar包
hadoop jar ~/lenovo/bigData/myapp/Sort.jar /user/hadoop/file2 /user/hadoop/output3
提示: 路徑 /user/hadoop/output3中的output3不用我們創建,該命令會自動幫我們創建的,但我們輸入的output3是要保證hdfs中沒有與之相同的名稱哦,不然會報錯的,其中 /user/hadoop/file2是我們創建好的保存測試文件的目錄哦!
2)、出現如下界面則爲成功運行
2、查看運行結果
1)、終端輸入以下命令查看我們排序的結果
hdfs dfs -cat /user/hadoop/output3/*
2)、查看結果如下所示:
3、運行結果分析
1)、最開始的三個文件數據及最後運行結果的數據如下所示:
上面的左邊爲file3.txt,中間爲file4.txt,右邊爲爲file5.txt
上面爲最終的運行結果
2)、在上面的結果中我們可以看出,運行出來的結果將我們上面三個文件的結果相結合爲一個文件
3)、除此之外,該代碼還實現了對數據的排序從小到大依次排序成功,達到了我們要求的結果展示!
4)、需要注意的是:如果要再次運行Sort.jar,需要首先刪除HDFS中的output3目錄,否則會報錯
4、實驗結束,關閉hadoop
stop-dfs.sh
以上就是本次博客的全部內容啦,通過對本次博客的閱讀,希望小夥伴理解如何通過java對MapReduce的數據進行操作,進而理解原理,這樣以後的編程中,就可以通過原理編程,而不是面向百度編程!
遇到問題的小夥伴記得留言評論哦,林君學長看到會爲大家解答的,這個學長不太冷!
陳一月的又一天編程歲月^ _ ^