標籤:mapreduce dex set arraylist int getc sub ted text
在大資料MapReduce作業開發中,我們經常會遇到一些大小表的join,這是如果這個小表足夠“小”的話,我們可以使用進行“map-join-side”,這要就可以有效降低reduce端的壓力,但是在常用的JDK的集合中的Map有些許雞肋,因此,各路大神們針對這個問題開發出了不同的集合架構,用以替換原創組合,下面我們具體介紹幾種常用的集合架構:
首先,我們設想了一個情境——計算不同事業部015、2016年老客,新客-轉化,新客-新增的使用者數量,這三種類型的使用者的定義如下:
老客:前一年和當前年均購買過服百事業部商品
新客-轉化:前一年購買過圖書,當前年購買了服百事業部商品
新客-新增:前一年什麼也沒買,當前年購買了服百事業部商品
因此,根據上述定義,舉例:2016年老客就是根據cust_id(使用者ID)在服百分類(fubaiArrayList )和服百總和(fubaiAllArrayList )兩個集合查看2016年和2015年均存在的使用者。2016年新客-轉化就是根據cust_id(使用者ID)在圖書(bookArrayList )存在2015年購買記錄,在服百分類(fubaiArrayList )和服百總和(fubaiAllArrayList )兩個集合查看2016年存在的使用者。2016年新客-新增就是根據cust_id(使用者ID)在所有使用者(allArrayList )不存在2015年購買記錄,但在服百分類(fubaiArrayList )和服百總和(fubaiAllArrayList )兩個集合查看2016年存在的使用者。
因此,根據上述解釋,我們構造了原始實現代碼為:
public static class Map extends Mapper<LongWritable, Text, Text, Text> {public static ArrayList<String> bookArrayList = null;public static ArrayList<String> fubaiAllArrayList = null;public static ArrayList<String> fubaiArrayList = null;public static ArrayList<String> allArrayList = null;@Overrideprotected void setup(Mapper<LongWritable, Text, Text, Text>.Context context)throws IOException, InterruptedException {bookArrayList = new ArrayList<String>();Configuration configuration = context.getConfiguration();FileSystem fs = FileSystem.get(configuration);InputStream in = null;BufferedReader reader = null;String tempString = null;Path book_path = new Path("/personal/zhoujie/recommend/book.csv");//14 15年全年購買過書的使用者名稱單if (fs.exists(book_path)) {in = fs.open(book_path);reader = new BufferedReader(new InputStreamReader(in, "utf-8"));while ((tempString = reader.readLine()) != null) {//年份 cust_id 圖書事業部String parts[] = tempString.split(TAB, -1);if(parts.length!=3)continue;bookArrayList.add(parts[0]+TAB+parts[1]);}}fubaiAllArrayList = new ArrayList<String>();Path fubai_all_path = new Path("/personal/zhoujie/recommend/fubaiall.csv");//14 15年全年購買過服百的全部使用者名稱單if (fs.exists(fubai_all_path)) {in = fs.open(fubai_all_path);reader = new BufferedReader(new InputStreamReader(in, "utf-8"));while ((tempString = reader.readLine()) != null) {//年份 cust_id 服百事業部總和String parts[] = tempString.split(TAB, -1);if(parts.length!=3)continue;fubaiAllArrayList.add(parts[0]+TAB+parts[1]);}}fubaiArrayList = new ArrayList<String>();Path fubai_path = new Path("/personal/zhoujie/recommend/fubaiall.csv");//14 15年全年購買過各服百事業部的全部使用者名稱單if (fs.exists(fubai_path)) {in = fs.open(fubai_path);reader = new BufferedReader(new InputStreamReader(in, "utf-8"));while ((tempString = reader.readLine()) != null) {//年份 cust_id 各服百事業部String parts[] = tempString.split(TAB, -1);if(parts.length!=3)continue;fubaiArrayList.add(parts[0]+TAB+parts[1]);}}allArrayList = new ArrayList<String>();Path all_path = new Path("/personal/zhoujie/recommend/all_order.csv");//14 15年全年下單使用者if (fs.exists(all_path)) {in = fs.open(all_path);reader = new BufferedReader(new InputStreamReader(in, "utf-8"));while ((tempString = reader.readLine()) != null) {//年份 cust_id 事業部String parts[] = tempString.split(TAB, -1);if(parts.length!=3)continue;allArrayList.add(parts[0]+TAB+parts[1]);}}}@Overrideprotected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)throws IOException, InterruptedException {InputSplit inputSplit = context.getInputSplit();String fileName = ((FileSplit) inputSplit).getPath().toString();if(fileName.contains("/personal/zhoujie/recommend/orderdetail/")){//date+TAB+app_id+TAB+permanentid+TAB+toProductid "APP全站" "服百事業部" order_id 單價 個數 cust_idString[] splited = value.toString().split(TAB, -1);if(splited.length!=10)return;String year = splited[0].substring(0, 4);String cust_id = splited[9];String department = splited[5];if("2015".equals(year)){if("服百事業部總和".equals(department)){//全部服百事業部if (fubaiAllArrayList.contains("2014"+TAB+cust_id)) {//說明14年在服百事業部買過,作為老使用者context.write(new Text("2015"+TAB+"服百事業部總和"+TAB+"老使用者"), new Text(cust_id));}else if(bookArrayList.contains("2014"+TAB+cust_id)){//說明14年在圖書事業部買過,作為新使用者-轉化使用者context.write(new Text("2015"+TAB+"服百事業部總和"+TAB+"新使用者-轉化使用者"), new Text(cust_id));}else if(!allArrayList.contains("2014"+TAB+cust_id)){//說明在14年沒有買過任何東西context.write(new Text("2015"+TAB+"服百事業部總和"+TAB+"新使用者-新增使用者"), new Text(cust_id));}}else {//各服百事業部if (fubaiArrayList.contains("2014"+TAB+cust_id)) {//說明14年在子服百事業部買過,作為老使用者context.write(new Text("2015"+TAB+department+TAB+"老使用者"), new Text(cust_id));}else if(bookArrayList.contains("2014"+TAB+cust_id)){//說明14年在圖書事業部買過,作為新使用者-轉化使用者context.write(new Text("2015"+TAB+department+TAB+"新使用者-轉化使用者"), new Text(cust_id));}else if(!allArrayList.contains("2014"+TAB+cust_id)){//說明在14年沒有買過任何東西context.write(new Text("2015"+TAB+department+TAB+"新使用者-新增使用者"), new Text(cust_id));}}}else if ("2016".equals(year)) {if("服百事業部總和".equals(department)){//全部服百事業部if (fubaiAllArrayList.contains("2015"+TAB+cust_id)) {//說明15年在服百事業部買過,作為老使用者context.write(new Text("2016"+TAB+"服百事業部總和"+TAB+"老使用者"), new Text(cust_id));}else if(bookArrayList.contains("2015"+TAB+cust_id)){//說明15年在圖書事業部買過,作為新使用者-轉化使用者context.write(new Text("2016"+TAB+"服百事業部總和"+TAB+"新使用者-轉化使用者"), new Text(cust_id));}else if(!allArrayList.contains("2015"+TAB+cust_id)){//說明在15年沒有買過任何東西context.write(new Text("2016"+TAB+"服百事業部總和"+TAB+"新使用者-新增使用者"), new Text(cust_id));}}else {//各服百事業部if (fubaiArrayList.contains("2015"+TAB+cust_id)) {//說明15年在子服百事業部買過,作為老使用者context.write(new Text("2016"+TAB+department+TAB+"老使用者"), new Text(cust_id));}else if(bookArrayList.contains("2015"+TAB+cust_id)){//說明15年在圖書事業部買過,作為新使用者-轉化使用者context.write(new Text("2016"+TAB+department+TAB+"新使用者-轉化使用者"), new Text(cust_id));}else if(!allArrayList.contains("2015"+TAB+cust_id)){//說明在15年沒有買過任何東西context.write(new Text("2016"+TAB+department+TAB+"新使用者-新增使用者"), new Text(cust_id));}}}}}}
一、JDK集合類
不用說,這個不是我們今天介紹的重點。正是由於原創組合的效率低下才有了這篇文章的存在。即上述代碼就是JDK集合類的實現代碼,經過多次測試,作業消耗時間大概在三個小時作業。
二、FastUtil集合架構
經過測試,FastUtil的集合類替換原創組合的時候,用時兩小時:
bookArrayList = new ObjectBigArrayBigList<String>()
三、HPPC集合架構
經過測試,FastUtil的集合類替換原創組合的時候,用時三分鐘:
bookArrayList = new ObjectHashSet<String>()
好快!
經過這三個集合類的測試,發現HPPC集合架構的查詢效率是最高的。
Java開發中各種集合架構簡介