杂谈记录——论Long类型的大数据量求交集

Posted 唐 昊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杂谈记录——论Long类型的大数据量求交集相关的知识,希望对你有一定的参考价值。

一、优化内外层比较的结构

『外层遍历 + 内层遍历』查找:
复杂度 O (NM) ,一般使用 contains () 检查是否包含

『外层遍历 + 内层 Hash』查找:
复杂度 O (N),一般将内层 List 转化为 HashSet 实现

『外层遍历 + 内层 bitMap』查找:
复杂度 O (N),一般将内层 List 转化为字节映射实现

package com.jw.demo.com.colllection.test;

import org.junit.Test;

import java.util.*;

public class SetOperation 

    @Test
    public void setOperation() 
        int size = 5000000;

        HashSet<Long> la = new HashSet<>(size);
        HashSet<Long> lb = new HashSet<>(size);

        for (int i = 0; i < 300000; i++) 
            la.add(Long.valueOf(i));
        

        for (int i = 0; i < 300000; i++) 
            lb.add(Long.valueOf(i));
        

        System.out.println("2.『外层Hash+内层list』查找:");
        outHastSetInnerHashSet(la, new ArrayList<>(lb));
        System.out.println("重复的数据有:"+la.size());

        //『外层list+内层Hash』查找:
        System.out.println("2.『外层list+内层Hash』查找:");
        outArrayListInnerHashSet(new ArrayList<>(la), lb);
        System.out.println("重复的数据有:"+la.size());

        System.out.println("2.『外层Hash+内层Hash』查找:");
        outHashSetInnerHashSet(la,lb);
        System.out.println("重复的数据有:"+la.size());

        receiveDefectList(new ArrayList<>(la),new ArrayList<>(lb));



    
    // 外层:HashSet,内层:HashSet
    private void outHastSetInnerHashSet (HashSet<Long>  listA, List<Long> listB) 
        long begin = System.currentTimeMillis();

        HashSet<Long> setB = new HashSet<>(listB);

        listA.retainAll(setB);
//        System.out.println("重复的数据有:"+listA.size());
        long end = System.currentTimeMillis();
        System.out.println("[HashSet-ArrayList]RetainAll耗时:" + (end - begin));
    



    // 外层:ArrayList,内层:HashSet
    private void outArrayListInnerHashSet(List<Long> listA, HashSet<Long> listB) 
        long begin = System.currentTimeMillis();
        ArrayList<Long> setA = new ArrayList<>(listA);
        Set<Long> set = new HashSet<>();
        Long[] arr = set.toArray(new Long[set.size()]);
        Arrays.sort(arr);

        setA.retainAll(listB);
//        System.out.println("重复的数据有:"+setA.size());
        long end = System.currentTimeMillis();
        System.out.println("[ArrayList-HashSet]RetainAll耗时:" + (end - begin));
    


    private void outHashSetInnerHashSet(HashSet<Long> la, HashSet<Long> lb) 
        long begin = System.currentTimeMillis();
        la.retainAll(lb);
//        System.out.println("重复的数据有:"+la.size());
        long end = System.currentTimeMillis();
        System.out.println("[HashSet-HashSet]RetainAll耗时:" + (end - begin));

    

    private void receiveDefectList(List<Long> firstArrayList, List<Long> secondArrayList) 
        long begin = System.currentTimeMillis();
        List<Long> resultList = new ArrayList<Long>();
        LinkedList<Long> result = new LinkedList<Long>(firstArrayList);// 大集合用linkedlist
        HashSet<Long> othHash = new HashSet<Long>(secondArrayList);// 小集合用hashset
        Iterator<Long> iter = result.iterator();// 采用Iterator迭代器进行数据的操作
        while(iter.hasNext())
            if(othHash.contains(iter.next()))
                iter.remove();
            
        
        resultList = new ArrayList<Long>(result);
        firstArrayList.clear();
        resultList.forEach(o-> firstArrayList.add(o));

        long end = System.currentTimeMillis();
        System.out.println("[ite-iterator]RetainAll耗时:" + (end - begin));
    

    private  void test3(List<Long> array1,List<Long> array2)

    
        Set<Long> set = new HashSet<>();
        Long[] arr = set.toArray(new Long[set.size()]);
        Arrays.sort(arr);
        // 通过HashMap:求两个集合中交集
        Map<Long,Integer> map=new HashMap<>();

        for(int i=0;i<Math.min(array1.size(),array2.size());i++)
        
            contains(map,array1.get(i));
            contains(map,array2.get(i));
        

        // 遍历
        for(Map.Entry<Long, Integer>m:map.entrySet())
        
            if(m.getValue()>1)
                array1.remove(m.getKey());
//                System.out.println(m.getKey());
        
    

    private  void contains(Map<Long,Integer>map,Long k)
    
        if(map.containsKey(k))
        
            Integer tmp=map.get(k);
            tmp++;
            map.put(k, tmp);
        
        else
        
            map.put(k,1);
        
    



二、java交集retainAll 和 Sets.intersection 性能比较(链接

三、用JDK方法求交集retainAll(链接

四、利用guava集合求交集(链接

五、利用bitmap求两个list的交集(链接

jar包获取地址(点击)

参考链接

1、十万以上数据的两个集合进行交集,差集运算,ArrayList为什么特别慢?HashSet为什么效率如此高?(地址
2、Java 中大集合 求交集的方法比较(地址
3、bitmap技术解析:redis与roaringBitnap(地址
4、一文读懂比BitMap有更好性能的Roaring Bitmap(地址

以上是关于杂谈记录——论Long类型的大数据量求交集的主要内容,如果未能解决你的问题,请参考以下文章

杂谈记录——论程序员式的幽默

杂谈 论实例化类的第六种方式

[杂谈]杂谈章5 问一些问题

杂谈 - 你不了解PHP的十件事情

数据的表示——进制

java数据类型