大量数据查找、去重:BitSet、BitMap


大数据处理算法之一:BitMap

如有错误,欢迎指正

1.(1)通过存储2表示是十进制的数进制位

如图:image

(2)可以快速排序/查找:bitmap.set(11),会直接在11的位上置为1,查询的时候直接查询这个位置是否是1,可以快速查找。

使用场景:

a.大量的黑名单号码需要存储,并且频繁访问,每次发送短信,这样就可以把黑名单号码存储到bitmap里面,通过boolean bitmap.get(11)方法,判断是否存在

b.现在有五十亿个int类型的正整数,要从中找出重复的数并返回?

思路:循环数据,把数据存到bitmap中,每次都判断是否存在在bitmap中,使用set(重复的数据只会保存一个)装bitmap中存在的数据,返回set即可

(3)

     1G = 1024M

     1M = 1024KB

     1KB = 1024B(字节)

     1M =(1024 * 1024)字节Byte

     1字节 = 8个二进制位(bit)

注意:有些时候在实际中,为了计算方便,计算机行业绝大多数的存储硬件设备生产制造商将1024进制改成了1000进制

2.使用过的bitmap和bitset

(1)com.sleepycat.je.utilint 包下面有一个BitMap,添加的参数是long类型的,里面也用到java.util包下面的BitSet(添加的参数类型是int的)。

依赖如下:


    com.sleepycat
    je
    5.0.73


(2)BitMap底层也是通过BitSet, 存进来的数是与65535L做逻辑与运算,(65535L:二进制中表示是16个1,转换成10进制正好是65535。unsingn int 一个整数是2个字节,有2*8个字符)
(3)如下是com.sleepycat包下的bitmap类,可以看出这个类也是使用了java.util包下的bitset

// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)

package com.sleepycat.je.utilint;

import com.sleepycat.je.EnvironmentFailureException;
import java.util.BitSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class BitMap {
    private static final int SEGMENT_SIZE = 16;
    private static final int SEGMENT_MASK = 65535;
    private Map bitSegments = new HashMap();

    public BitMap() {
    }

    public void set(long index) throws IndexOutOfBoundsException {
        if(index < 0L) {
            throw new IndexOutOfBoundsException(index + " is negative.");
        } else {
            BitSet bitset = this.getBitSet(index, true);
            if(bitset == null) {
                throw EnvironmentFailureException.unexpectedState(index + " is out of bounds");
            } else {
                int useIndex = this.getIntIndex(index);
                bitset.set(useIndex);
            }
        }
    }

    public boolean get(long index) throws IndexOutOfBoundsException {
        if(index < 0L) {
            throw new IndexOutOfBoundsException(index + " is negative.");
        } else {
            BitSet bitset = this.getBitSet(index, false);
            if(bitset == null) {
                return false;
            } else {
                int useIndex = this.getIntIndex(index);
                return bitset.get(useIndex);
            }
        }
    }

    private BitSet getBitSet(long index, boolean allowCreate) {
        Long segmentId = Long.valueOf(index >> 16);
        BitSet bitset = (BitSet)this.bitSegments.get(segmentId);
        if(allowCreate && bitset == null) {
            bitset = new BitSet();
            this.bitSegments.put(segmentId, bitset);
        }

        return bitset;
    }

    private int getIntIndex(long index) {
        return (int)(index & 65535L);
    }

    int getNumSegments() {
        return this.bitSegments.size();
    }

    int cardinality() {
        int count = 0;

        BitSet b;
        for(Iterator iter = this.bitSegments.values().iterator(); iter.hasNext(); count += b.cardinality()) {
            b = (BitSet)iter.next();
        }

        return count;
    }
}

补充:左移<<变大,左移多少位,就在后面加几个0;右移>>变小,右移多少位,就在末尾砍掉几个数。

你可能感兴趣的:(java)