在大数据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年存在的用户。
因此,根据上述解释,我们构造了原始实现代码为:

  1. public static class Map extends Mapper<LongWritable, Text, Text, Text> {
  2.  
  3. public static ArrayList<String> bookArrayList = null;
  4. public static ArrayList<String> fubaiAllArrayList = null;
  5. public static ArrayList<String> fubaiArrayList = null;
  6. public static ArrayList<String> allArrayList = null;
  7.  
  8. @Override
  9. protected void setup(Mapper<LongWritable, Text, Text, Text>.Context context)
  10. throws IOException, InterruptedException {
  11. bookArrayList = new ArrayList<String>();
  12. Configuration configuration = context.getConfiguration();
  13. FileSystem fs = FileSystem.get(configuration);
  14. InputStream in = null;
  15. BufferedReader reader = null;
  16. String tempString = null;
  17. Path book_path = new Path("/personal/zhoujie/recommend/book.csv");//14 15年全年购买过书的用户名单
  18. if (fs.exists(book_path)) {
  19. in = fs.open(book_path);
  20. reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
  21. while ((tempString = reader.readLine()) != null) {
  22. //年份 cust_id 图书事业部
  23. String parts[] = tempString.split(TAB, -1);
  24. if(parts.length!=3)continue;
  25. bookArrayList.add(parts[0]+TAB+parts[1]);
  26. }
  27. }
  28. fubaiAllArrayList = new ArrayList<String>();
  29. Path fubai_all_path = new Path("/personal/zhoujie/recommend/fubaiall.csv");//14 15年全年购买过服百的全部用户名单
  30. if (fs.exists(fubai_all_path)) {
  31. in = fs.open(fubai_all_path);
  32. reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
  33. while ((tempString = reader.readLine()) != null) {
  34. //年份 cust_id 服百事业部总和
  35. String parts[] = tempString.split(TAB, -1);
  36. if(parts.length!=3)continue;
  37. fubaiAllArrayList.add(parts[0]+TAB+parts[1]);
  38. }
  39. }
  40. fubaiArrayList = new ArrayList<String>();
  41. Path fubai_path = new Path("/personal/zhoujie/recommend/fubaiall.csv");//14 15年全年购买过各服百事业部的全部用户名单
  42. if (fs.exists(fubai_path)) {
  43. in = fs.open(fubai_path);
  44. reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
  45. while ((tempString = reader.readLine()) != null) {
  46. //年份 cust_id 各服百事业部
  47. String parts[] = tempString.split(TAB, -1);
  48. if(parts.length!=3)continue;
  49. fubaiArrayList.add(parts[0]+TAB+parts[1]);
  50. }
  51. }
  52. allArrayList = new ArrayList<String>();
  53. Path all_path = new Path("/personal/zhoujie/recommend/all_order.csv");//14 15年全年下单用户
  54. if (fs.exists(all_path)) {
  55. in = fs.open(all_path);
  56. reader = new BufferedReader(new InputStreamReader(in, "utf-8"));
  57. while ((tempString = reader.readLine()) != null) {
  58. //年份 cust_id 事业部
  59. String parts[] = tempString.split(TAB, -1);
  60. if(parts.length!=3)continue;
  61. allArrayList.add(parts[0]+TAB+parts[1]);
  62. }
  63. }
  64. }
  65.  
  66. @Override
  67. protected void map(LongWritable key, Text value, Mapper<LongWritable, Text, Text, Text>.Context context)
  68. throws IOException, InterruptedException {
  69. InputSplit inputSplit = context.getInputSplit();
  70. String fileName = ((FileSplit) inputSplit).getPath().toString();
  71.  
  72. if(fileName.contains("/personal/zhoujie/recommend/orderdetail/")){
  73. //date+TAB+app_id+TAB+permanentid+TAB+toProductid "APP全站" "服百事业部" order_id 单价 个数 cust_id
  74. String[] splited = value.toString().split(TAB, -1);
  75. if(splited.length!=10)return;
  76. String year = splited[0].substring(0, 4);
  77. String cust_id = splited[9];
  78. String department = splited[5];
  79. if("2015".equals(year)){
  80. if("服百事业部总和".equals(department)){//全部服百事业部
  81. if (fubaiAllArrayList.contains("2014"+TAB+cust_id)) {//说明14年在服百事业部买过,作为老用户
  82. context.write(new Text("2015"+TAB+"服百事业部总和"+TAB+"老用户"), new Text(cust_id));
  83. }else if(bookArrayList.contains("2014"+TAB+cust_id)){//说明14年在图书事业部买过,作为新用户-转化用户
  84. context.write(new Text("2015"+TAB+"服百事业部总和"+TAB+"新用户-转化用户"), new Text(cust_id));
  85. }else if(!allArrayList.contains("2014"+TAB+cust_id)){//说明在14年没有买过任何东西
  86. context.write(new Text("2015"+TAB+"服百事业部总和"+TAB+"新用户-新增用户"), new Text(cust_id));
  87. }
  88. }else {//各服百事业部
  89. if (fubaiArrayList.contains("2014"+TAB+cust_id)) {//说明14年在子服百事业部买过,作为老用户
  90. context.write(new Text("2015"+TAB+department+TAB+"老用户"), new Text(cust_id));
  91. }else if(bookArrayList.contains("2014"+TAB+cust_id)){//说明14年在图书事业部买过,作为新用户-转化用户
  92. context.write(new Text("2015"+TAB+department+TAB+"新用户-转化用户"), new Text(cust_id));
  93. }else if(!allArrayList.contains("2014"+TAB+cust_id)){//说明在14年没有买过任何东西
  94. context.write(new Text("2015"+TAB+department+TAB+"新用户-新增用户"), new Text(cust_id));
  95. }
  96. }
  97. }else if ("2016".equals(year)) {
  98. if("服百事业部总和".equals(department)){//全部服百事业部
  99. if (fubaiAllArrayList.contains("2015"+TAB+cust_id)) {//说明15年在服百事业部买过,作为老用户
  100. context.write(new Text("2016"+TAB+"服百事业部总和"+TAB+"老用户"), new Text(cust_id));
  101. }else if(bookArrayList.contains("2015"+TAB+cust_id)){//说明15年在图书事业部买过,作为新用户-转化用户
  102. context.write(new Text("2016"+TAB+"服百事业部总和"+TAB+"新用户-转化用户"), new Text(cust_id));
  103. }else if(!allArrayList.contains("2015"+TAB+cust_id)){//说明在15年没有买过任何东西
  104. context.write(new Text("2016"+TAB+"服百事业部总和"+TAB+"新用户-新增用户"), new Text(cust_id));
  105. }
  106. }else {//各服百事业部
  107. if (fubaiArrayList.contains("2015"+TAB+cust_id)) {//说明15年在子服百事业部买过,作为老用户
  108. context.write(new Text("2016"+TAB+department+TAB+"老用户"), new Text(cust_id));
  109. }else if(bookArrayList.contains("2015"+TAB+cust_id)){//说明15年在图书事业部买过,作为新用户-转化用户
  110. context.write(new Text("2016"+TAB+department+TAB+"新用户-转化用户"), new Text(cust_id));
  111. }else if(!allArrayList.contains("2015"+TAB+cust_id)){//说明在15年没有买过任何东西
  112. context.write(new Text("2016"+TAB+department+TAB+"新用户-新增用户"), new Text(cust_id));
  113. }
  114. }
  115. }
  116. }
  117. }
  118. }

一、JDK集合类
不用说,这个不是我们今天介绍的重点。正是由于原始集合的效率低下才有了这篇文章的存在。即上述代码就是JDK集合类的实现代码,经过多次测试,作业消耗时间大概在三个小时作业。
二、FastUtil集合框架
经过测试,FastUtil的集合类替换原始集合的时候,用时两小时:
bookArrayList = new ObjectBigArrayBigList<String>()
三、HPPC集合框架
经过测试,FastUtil的集合类替换原始集合的时候,用时三分钟:
bookArrayList = new ObjectHashSet<String>()
好快!
经过这三个集合类的测试,发现HPPC集合框架的查询效率是最高的。

Java开发中各种集合框架简介的更多相关文章

  1. 吴裕雄--天生自然 JAVA开发学习:集合框架

    import java.util.*; public class Test{ public static void main(String[] args) { List<String> l ...

  2. Java中的集合框架(上)

    Java中的集合框架概述 集合的概念: Java中的集合类:是一种工具类,就像是容器,存储任意数量的具有共同属性的对象. 集合的作用: 1.在类的内部,对数据进行组织: 2.简单的快速的搜索大数据量的 ...

  3. Java中的集合框架-Collection(一)

    一,Collection接口 在日常的开发工作中,我们经常使用数组,但是数组是有很多的局限性的,比如:数组大小固定后不可修改,只能存储基本类型的值等等. 基于数组的这些局限性,Java框架就产生了用于 ...

  4. Java中的集合框架-Collections和Arrays

    上一篇<Java中的集合框架-Map>把集合框架中的键值对容器Map中常用的知识记录了一下,本节记录一下集合框架的两个工具类Collections和Arrays 一,Collections ...

  5. Java中的集合框架-Map

    前两篇<Java中的集合框架-Commection(一)>和<Java中的集合框架-Commection(二)>把集合框架中的Collection开发常用知识点作了一下记录,从 ...

  6. 菜鸟日记之 java中的集合框架

    java中的集合框架图 如图所示:java中的集合分为两种Collection和Map两种接口 可分为Collection是单列集合和Map的双列集合 Collection单列集合:继承了Iterat ...

  7. Java中的集合框架-Collection(二)

    上一篇<Java中的集合框架-Collection(一)>把Java集合框架中的Collection与List及其常用实现类的功能大致记录了一下,本篇接着记录Collection的另一个子 ...

  8. JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue

    前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...

  9. JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序

    前言:暑期应该开始了,因为小区对面的小学这两天早上都没有像以往那样一到七八点钟就人声喧闹.车水马龙. 前两篇文章介绍了Collection框架的主要接口和常用类,例如List.Set.Queue,和A ...

随机推荐

  1. Wireshark协议分析工具应用

    一.Wireshark简介与安装 Wireshark(前称Ethereal)是一个网络封包分析软件.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料.Wireshark使用W ...

  2. 关于miniconda的安装,配置以及包批量安装和使用

    由于时间很晚了.就不写废话了. conda官方文档地址:http://conda.pydata.org/docs/ 一切其实都可以从miniconda的文档找到,这里只纪录自己操作的时候遇到的值得一说 ...

  3. HashMap的实现原理--链表散列

    1.    HashMap概述 HashMap是基于哈希表的Map接口的非同步实现.此实现提供所有可选的映射操作,并允许使用null值和null键.此类不保证映射的顺序,特别是它不保证该顺序恒久不变. ...

  4. html 框架 內聯框架

    框架的作用:可以在瀏覽器同時顯示不止一個html頁面.一個html文檔也叫做一個框架. 垂直框架:設置窗口垂直排列顯示成一行 <frameset cols="20%,80%" ...

  5. 睡前小dp-hdu3853-概率dp

    http://acm.hdu.edu.cn/showproblem.php?pid=3853 膜猴烧酒madoka 讲定义为dp[i][j] 位置为ij的魔法值期望,可以发现dp[i][j] = dp ...

  6. Hopcroft-Carp 算法模板 自用

    #include <iostream> #include <cstdio> #include <cstring> #include <queue> #d ...

  7. day27 多态 多继承 接口类 抽象类

    简单来说:多态就是指一个相同的方法名在不同的对象调用的时候实现一样或者不一样的方法实例1: 动物类有个方法 "嚎叫" 狗类也有个方法 "嚎叫" 猫类继承了动物类 ...

  8. Sublime text3 插件LiveReload 实现实时预览

    1.首先要安装插件LiveReload Sublime text3. 菜单 preferences->packages control,输入install.. 回车,输入LiveReload回车 ...

  9. BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

    题意 有 \(n\) 个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪. 因此,对于不同的开枪顺序,最后死的人也不同. 问最 ...

  10. 在Java Web程序中使用监听器可以通过以下两种方法

    之前学习了很多涉及servlet的内容,本小结我们说一下监听器,说起监听器,编过桌面程序和手机App的都不陌生,常见的套路都是拖一个控件,然后给它绑定一个监听器,即可以对该对象的事件进行监听以便发生响 ...