【算法】求多个数组中的交集(Java语言实现)

简介:

  最近在工作中遇到一个问题,需要离线比较两张Mongodb表的差异:大小差异,相同的个数。

  所以,我将导出的bson文件转成了json文件(2G以上),一条记录正好是一行。

 

问题:

  因此我将以上问题转换成了比较两个(本例考虑多个)超大数组的交集!所以要求时间复杂度、空间复杂度应该尽可能的低!

 

降低内存:

  由于要将文件的每一行都读到内存里,如果行的长度比较大的话,内存肯定是不够的!

  所以我想到的办法是讲每一行压缩成md5编码。 String line = md5(line)。然后再将新的line读入内存。

  如此,通常1000万行记录读到内存里大概是800MB(这里有点忘了,反正大概是800MB~1GB)。

 

(我使用的idea编辑器,跟eclipse可能在某些地方有点差别。另外,本例一字符数组为例,并且假设数组元素不重复!!!)

 

MapReduce:

/**
 * 这里以字符串数组为例
 * 采用mapreduce原理,生成一组以数组元素为key,相同元素的个数为value的中间键值对
 * 这里将mapreduce分开来写方便阅读,也可以写成一个函数
 * @param arrays
 */
public static HashMap<String, Integer> mapReduce(final String[]... arrays) {
    HashMap<String, Integer> 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);
            }
        }
    }

    return reduce(hashMap, arrays.length);
}

 

Reduce:

/**
 * 统计出相同元素个数正好是数组(参数)个数的元素(也就是每个数组中都有的元素)
 * 移除value不等于数组参数个数的键值对,并组成新的map
 * @param hashMap
 * @param arrayCount
 * @return
 */
public static HashMap<String, Integer> reduce(HashMap<String, Integer> hashMap, final Integer arrayCount) {
    Iterator<String> 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();
} } return hashMap; }

 

eg:

/**
 * 本例假设同一数组中的元素不重复
 * @param args
 */
public static void main(String[] args) {
    HashMap<String, Integer> 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());
}

 

posted @ 2016-03-24 19:00  高手教程  阅读(2596)  评论(0编辑  收藏  举报