简介:
最近在工作中遇到一个问题,需要离线比较两张Mongodb表的差异:大小差异,相同的个数。
所以,我将导出的bson文件转成了json文件(2G以上),一条记录正好是一行。
问题:
因此我将以上问题转换成了比较两个(本例考虑多个)超大数组的交集!所以要求时间复杂度、空间复杂度应该尽可能的低!
降低内存:
由于要将文件的每一行都读到内存里,如果行的长度比较大的话,内存肯定是不够的!
所以我想到的办法是讲每一行压缩成md5编码。 String line = md5(line)。然后再将新的line读入内存。
如此,通常1000万行记录读到内存里大概是800MB(这里有点忘了,反正大概是800MB~1GB)。
(我使用的idea编辑器,跟eclipse可能在某些地方有点差别。另外,本例一字符数组为例,并且假设数组元素不重复!!!)
MapReduce:
/*** 这里以字符串数组为例
* 采用mapreduce原理,生成一组以数组元素为key,相同元素的个数为value的中间键值对
* 这里将mapreduce分开来写方便阅读,也可以写成一个函数
*@paramarrays*/
public static HashMap mapReduce(finalString[]... arrays) {
HashMap hashMap = new HashMap<>();//不要看到两个for就以为时间复杂度为n^2,这里只是有多个数组参数而已
for(String[] array : arrays) {for(String elem : array) {if(hashMap.containsKey(elem)) {
hashMap.put(elem, hashMap.get(elem)+ 1);
}else{
hashMap.put(elem,1);
}
}
}returnreduce(hashMap, arrays.length);
}
Reduce:
/*** 统计出相同元素个数正好是数组(参数)个数的元素(也就是每个数组中都有的元素)
* 移除value不等于数组参数个数的键值对,并组成新的map
*@paramhashMap
*@paramarrayCount
*@return
*/
public static HashMap reduce(HashMap hashMap, finalInteger arrayCount) {
Iterator iter =hashMap.keySet().iterator();
String key;while(iter.hasNext()) {
key=iter.next();if (!hashMap.get(key).equals(arrayCount)) {
//不能使用 hashMap.remove(key); 会出现异常, 见http://www.cnblogs.com/yrqiang/p/5344531.html
iter.remove();
}
}returnhashMap;
}
eg:
/*** 本例假设同一数组中的元素不重复
*@paramargs*/
public static voidmain(String[] args) {
HashMap hashMap = new HashMap<>();
String[] arr1= {"aa", "bb", "cc", "dd"};
String[] arr2= {"11", "bb", "cc", "dd", "ee"};
String[] arr3= {"22", "bb", "cc", "dd", "ee", "ff"};
hashMap=mapReduce(arr1, arr2, arr3);
System.out.println(hashMap);
System.out.println(hashMap.size());
}