(自定义)BitMap在大数据下实现去重

(自定义)BitMap在大数据下实现去重

【BitMap】:bitmap是很有用的结构。所谓的bitmap就是用一个bit位来标记某个元素,而数组下标是该元素。

【方式一:用byte[]数组计数实现BitMap】: 参考 Java中Bitmap的实现

package com.caox.utils;

import lombok.extern.slf4j.Slf4j;

/**
 * @author : nazi
 * @version : 1.0
 * @date : 2019/7/9 15:14
 */
@Slf4j
public class BitMapUtils {
    /**
     * 创建bitmap数组
     */
    public static byte[] create(int n){
        byte[] bits = new byte[getIndex(n) + 1];

        for(int i = 0; i < n; i++){
            add(bits, i);
        }

        System.out.println(contains(bits, 11));

        int index = 1;
        for(byte bit : bits){
            System.out.println("-------" + index++ + "-------");
            showByte(bit);

        }

        return bits;
    }

    /**
     * 标记指定数字(num)在bitmap中的值,标记其已经出现过<br/>
     * 将1左移position后,那个位置自然就是1,然后和以前的数据做|,这样,那个位置就替换成1了
     * @param bits
     * @param num
     */
    public static void add(byte[] bits, int num){
        bits[getIndex(num)] |= 1 << getPosition(num);
    }

    /**
     * 判断指定数字num是否存在<br/>
     * 将1左移position后,那个位置自然就是1,然后和以前的数据做&,判断是否为0即可
     * @param bits
     * @param num
     * @return
     */
    public static boolean contains(byte[] bits, int num){
        return (bits[getIndex(num)] & 1 << getPosition(num)) != 0;
    }

    /**
     * num/8得到byte[]的index
     * @param num
     * @return
     */
    public static int getIndex(int num){
        return num >> 3;
    }

    /**
     * num%8得到在byte[index]的位置
     * @param num
     * @return
     */
    public static int getPosition(int num){
        return num & 0x07;
    }

    /**
     * 重置某一数字对应在bitmap中的值<br/>
     * 对1进行左移,然后取反,最后与byte[index]作与操作。
     * @param bits
     * @param num
     */
    public static void clear(byte[] bits, int num){
        bits[getIndex(num)] &= ~(1 << getPosition(num));
    }

    /**
     * 打印byte类型的变量<br/>
     * 将byte转换为一个长度为8的byte数组,数组每个值代表bit
     */

    public static void showByte(byte b){
        byte[] array = new byte[8];
        for(int i = 7; i >= 0; i--){
            array[i] = (byte)(b & 1);
            b = (byte)(b >> 1);
        }

        for (byte b1 : array) {
            System.out.print(b1);
            System.out.print(" ");
        }

        System.out.println();
    }

    public static void main(String[] args) {
        int n = 101;
        byte[] bits =  BitMapUtils.create(n);
        log.info("call  检测是否包含其中 :{}", BitMapUtils.contains(bits,100));
    }
}

【方式二:用int[]数组计数实现BitMap】 :参考文献:Java面试中常用的BitMap代码

setBit的流程如下:

  1. 求出belowIndex并且得到int值;
  2. 求出offset并且利用“或运算”将刚才得到的int值的offset位置置为1;

getBit的流程如下:

  1. 求出belowIndex并且得到int值;
  2. 求出offset,之后利用“与运算”取出offset位置的值将其变为01后返回;
package com.caox.utils;

/**
 * @author : nazi
 * @version : 1.0
 * @date : 2019/7/10 13:35
 */
public class BitMap {
    private long length;
    private static int[] bitsMap;

    /**
     * 构造函数中传入数据中的最大值
     * @param length
     */
    public BitMap(long length) {
        this.length = length;
        // 根据长度算出,所需数组大小
        bitsMap = new int[(int) (length >> 5) + ((length & 31) > 0 ? 1 : 0)];
    }

    public int getBit(long index) {
        int intData = bitsMap[(int) ((index - 1) >> 5)];
        int offset = (int) ((index - 1) & 31);
        return intData >> offset & 0x01;
    }


    public void setBit(long index) {
        // 求出该index - 1所在bitMap的下标
        int belowIndex = (int) ((index - 1) >> 5);
        // 求出该值的偏移量(求余)
        int offset = (int) ((index - 1) & 31);
        int inData = bitsMap[belowIndex];
        bitsMap[belowIndex] = inData | (0x01 << offset);
    }
    public static void main(String[] args) {
        BitMap bitMap = new BitMap(32);
        bitMap.setBit(32);
        System.out.println(bitMap.getBit(1));
        System.out.println(bitMap.getBit(32));
    }
}

【使用BitMap进行数据去重:采用byte[]实现】: 

package com.caox.utils;

import java.util.Arrays;

/**
 * @author : nazi
 * @version : 1.0
 * @date : 2019/7/10 14:53
 */
public class BitMapRepRemove {
    public static byte[] flags;


    public static void main(String[] args) {

        int[] array = {255, 1024, 1024, 0, 65536, 0, 1024, 8888, 9999, 1111, 8888};

        int length = 65536 + 1;
        flags = new byte[(int) (length >> 3) + ((length & 7) > 0 ? 1 : 0)];

        int index = 0;
        for(int num : array) {
            if( getFlags(num) != 1) {
                //未出现的元素
                array[index] = num;
                index = index + 1;
                //设置标志位
                setFlags(num);
            }
        }
        array = Arrays.copyOf(array, index);
        System.out.println(Arrays.toString(array));
        System.out.println(array.length);
    }

    public static void setFlags(int num) {
        int offset = num & (0x07);
        flags[num >> 3] |= 0x01 << offset;
    }

    public static int getFlags(int num) {
        int offset = num & (0x07);
        return flags[num >> 3] >> offset & 0x01;
    }
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值