Java面试笔试指南(七)---海量数据处理

通过对海量数据的挖掘能有效地揭示用户的行为模式,加深对用户需求的理解,提取用户的集体智慧,从而为研发人员决策提供依据,提升产品和用户体验,进而占领市场

基础方法

1、Hash法

Hash一般被称为散列,一种映射关系(即给定一个数据元素,其关键字为key,按一个确定的散列函数计算出hash(key),并把hash(key)作为关键字key对应元素的存储地址,再进行数据元素的插入和检索操作),散列函数就是一种将任意长度的消息压缩到某个固定长度的消息摘要的函数

Hash主要是用来进行“快速存取”,在0(1)内就可以找到目标元素,或者判断其是否存在

  • 散列表:是具有固定大小(一般为质数)的数组
  • 冲突:就是两个关键字映射到同一个存储地址的情况

散列函数的特点:

  1. 运算应该尽可能简单
  2. 函数的值域必须在散列表的范围内
  3. 尽可能减少冲突

散列函数的构建方法:

  1. 直接寻址法:取关键字或关键字的某个线性函数值为散列地址,h(key)=a*key+b(这种方法不会产生冲突,但是由于它没有压缩,当关键字集合很大时,这种方法不肯能实现地址编码的散列)
  2. 取模法:选择一个合适的正整数p,h(key)=key mod p(如果选择的是比较大的素数,效果比价好,一般选取p为散列表大小)
  3. 数字分析法:分析关键字(简单直观,但是需要预先知道每个关键字的情况)
  4. 折叠法:将关键字分成位数为t的几部分,然后把各部分按位对齐进行相加,将所得的和舍弃进位,留下t位作为散列地址(当关键字位数很多,且关键字中每位上数字分布比较均匀,效果好)
  5. 平方取中法:将关键字进行平方运算,然后从结果的中间取出若干位,位数与散列地址位数相同,将其作为散列地址
  6. 除留余数法:取关键字除以某个数p(p不大于散列表的大小)的余数作为散列地址,h(key)=key%p
  7. 随机数法:选择一个随机函数,然后用关键字key 的随机函数值作为散列地址,h(key)=(key),关键字的长度不相等时,效果好

解决冲突的方法:

  1. 开放地址法:当发生冲突时,在散列表中再按照某种方法继续探测其他的存储地址,直到找到空闲的地址【对于利用开放地址法处理冲突的散列表,删除一个元素时不能直接删除,这会影响其他相同散列地址的元素,通常采用设定一个特殊的标志的方式表示该元素已经被删除】
  2. 链地址法:若散列表空间为[0,m-1],则设置一个由m个指针组成的一维数组CH[m],然后在寻找关键字散列地址的过程中,所以散列地址为i 的元素都插入头指针问CH[i]的链表中
  3. 再散列法:当发生冲突,使用2或3进行再散列,直到没有冲突,时间成本大
  4. 建立一个公共溢出区:假设散列函数的值域为[0,m-1],则设向量Hashtable[0…m-1]为基本表,另外设立存储空间向量OverTable[0…v]用以存储发生冲突的记录

2、Bit-map法

使用位数组来表示某些元素是否存在,具体而言,Bit-map法的结果是生成一个N位长的串,每位上以“0”或“1”表示需要排序的集合中的数,Bit-map的时间复杂度为o(n),比一般排序快,以空间换时间,在排序前需要知道集合大小,而且集合中元素的最大重复次数必须已知,最好是稠集数据

适用于海量数据的快速查找,判重、删除

具体过程:

  1. 扫描一遍集合,找出集合中的最大元素,按照最大元素创建长度为max的新数组
  2. 再次扫描集合,遇到一个元素就将新数组中小板为元素值的位置置为1

Bit-map除了可以判断数据是否重复,还可以判断某个数据是否存在

3、Bloom Filter

一种空间效率和时间效率都很高的随机数据结构,可用来检测一个元素是否属于一个集合,但是牺牲了正确率;当判断某个元素不属于这个集合,那么该元素一定不属于这个集合,如果判断一个元素属于这个集合,那么该元素不一定属于这个集合

Bloom Filter是位数组和Hash函数的联合使用,具体过程:

  1. 创建一个包含m位的数组,初始化为全0
  2. 定义k个不同的Hash函数,每个函数都可以将集合中的元素映射到位数组的某一位
  3. 向集合中插入元素,根据k个Hash函数得到k个值,并在位数组中设置为1
  4. 判断一个元素是否存在,根据k个Hash函数得到k个值,判断这个k位在数组中是否为1,全为1,可能在,不全为1,肯定不在

插入的元素越多,错判的概率越高,只能插入元素不能删除元素

4、数据库优化法

  1. 优秀的数据库管理工具
  2. 数据分区
  3. 索引
  4. 缓存机制
  5. 加大虚存
  6. 分批处理
  7. 使用临时表和中间表
  8. 优化查询语句
  9. 使用视图
  10. 使用存储过程
  11. 用排序来取代非顺序存取
  12. 使用采样数据进行数据挖掘

5、倒排索引法

倒排索引是目前搜索引擎公司对搜索引擎最常用的存储方法,按照关键字建立索引,用来存储在权威搜索下某个单词在一个文档或者一组文档中的存储位置的映射,是文档检索系统中最常用的数据结构

2种不同的反向索引形式:

  • 一条记录的水平反向索引,包含每个引用单词的文档的列表
  • 一个单词的水平反向索引,包含每个单词出现在文档中的位置(提供更多的兼容性,但是需要更多的时间和空间)

正向索引:用来存储每个文档的单词的列表,正向索引的查询往往满足每个文档有序频繁的全文查询和每个单词在校验文档中的验证这样的查询,(文档指向了它包含的那些单词)

反向索引:(单词指向了包含它的文档)

6、外排序法

当带排序的对象数目特别多时,在内存中不能一次处理,必须把它们以文件的形式存放于外存,排序时再把它们一部分一部分地调入内存进行处理,一般采用归并排序实现外排序

具体步骤:

  1. 生成若干初始归并段(文件预处理),按照内存大小划分
  2. 将子文件调入内存,采用有效的内排序后送回外存
  3. 对初始段进行多路归并,是的有序的归并段之间扩大,最后在外存上形成整个文件的单一归并段

外排序适用于大数据的排序以及去重复

7、Trie树

用于快速字符串检索的多叉树结构,利用字符串的公共前缀来减少时空开销

Trie树的特点:

  • 根节点不包含字符
  • 从根节点到某一个节点,路径上经过的字符连接起来,为该节点对应的字符串
  • 每个节点的所以子节点包含的字符都不相同

一般情况下,Trie树的结构都采用26叉树,每个节点对应一个字母,查找的时候进行字母匹配,算法时间复杂度就是单词长度,效率很高

Trie树的典型应用统计和排序大量的字符串,在搜索引擎中用于文本词频统计,有点是最大限度的减少无谓字符串比较们潮汛效率比散列表高

Trie树适用于数据量大,重复多,但是数据种类小可以放在内存中的情况

8、堆

堆是一种树形结构,每个节点都有一个值,一般指二叉堆

描述 堆类型 作用
求海量数据中前n大/小的值的中位数 最大堆 求前n小
同上 最小堆 求前n大
同上 双堆 中位数

9、双层桶法

类似于分治的一种思想

10、MapReduce法

Hadoop之MapReduce:http://blog.csdn.net/wee_mita/article/details/72721761

3、经典案例

top K

在海量数据中找出出现频率最高的前k个数,从海量数据中找出最大的前k个数

解决方案
1、分治+Trie树/hash|+小根堆:

  1. 先将数据按照hash方法分解为多个小数据集
  2. 使用Trie树或者hash统计每个数据集中的词频
  3. 使用小根堆求每个数据中出现频率最高的k个数
  4. 在所以top k中最终的top k

2、MapReduce解决:
一个map 两个reduce

  • map切分数据
  • reduce1统计词频
  • reduce2求top k

你可能感兴趣的:(Java)