Java開發中各種集合框架簡介

在大數據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;

@Override
protected 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]);
}
}
}

@Override
protected 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_id
String[] 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集合框架的查詢效率是最高的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章