10亿条编码,限制在1个G内存,怎么在1秒内,查询一个编码是否存在

正常情况下,我们肯定是使用HashMap来判断

但是我们来计算下,10亿条数据所占用的内存

int 占用4个字节

4*1000000000/1024/1024/1024=3.725G内存

超过了1个G的内存,所以不能使用HashMap

我们可以使用位图BitMap,也就是二进制字节数组

一个字节占8个bit,我们吧编码当做索引,不占用内存,数组中的值占用内存。

前提是我们的编码都是正整数才能使用位图

我们来计算下所占用的内存

1000000000/8/1024/1024/1024=0.116G

小于1个G,所以我们使用位图,如果索引存在设置为1,不存在不管他

这样在查询的时候直接查询索引位置是不是1,就能拿到结果

这样时间复杂度就是O(1)的,在1秒内就能查询到

下面看代码

package com.example.demo.entity;

/**
 * 二进制字节数组  就是位图BitMap
 * 1个字节byte占8个位=8bit 0 0 0 0 0 0 0 0
 */
public class BitMap {

    private int size;

    private byte[]data;

    public BitMap(int size){
        this.size=size;
        //10/8=1,不够2个字节,那么需要去借7个
        //所以10+7=17/8=2,所以10个长度,放2个字节数组

        this.data=new byte[(size+7)/8];
    }


    /**
     * 存储二进制字节数组对应的索引 设置为1
     * num当做索引位置
     * 时间复杂度o(1)
     */
    public void set(int num){
        if(num>=size){
            //索引越界
            return;
        }
        //找到要存放到那个字节数组中
        //10/8=1 数组从0开始,所以0表示第一个数组,1表示第二个数组
        //也就是10要放到第二个字节数组中
        int byteIndex=num/8;
        //获取原字节数组中的数据
        byte b=data[byteIndex];

        //7 6 5 4 3 2 1 0         这里是索引的位置
        //0 0 0 0 0 0 0 0         这里是第一个字节数组存放的0还是1

        //15 14 13 12 11 10 9 8   这里是索引的位置
        //0  0  0  0  0  0  0 0   这里是第二个字节数组存放的0还是1
        //获取新的元素要左移的位置
        //num%8表示10%8=2 表示右边距离的位置
        //7是下标最后一位,左边减去右边,就是15那个位置要往右移动到10的位置
        //左边是高位  右边是低位
        int zy=7-(num%8);
        //从左往右走 和之前的数据取或 有1就是1,说明之前存在1,不改变原来的数据,
        //如果是新的数据1,那么放入1,这样新的数据有1,旧的数据也有1,这样在重新赋值给字节数组
        //这样就添加成功了
        data[byteIndex]=(byte)(b|1<<zy);
    }


    /**
     * 从字节数组中获取是否存在
     * num当做索引位置
     * 时间复杂度o(1)
     */
    public boolean get(int num){
        if(num>=size){
            //索引越界
            return false;
        }
        //找到要存放到那个字节数组中
        //10/8=1 数组从0开始,所以0表示第一个数组,1表示第二个数组
        //也就是10要放到第二个字节数组中
        int byteIndex=num/8;
        //获取原字节数组中的数据
        byte b=data[byteIndex];

        //7 6 5 4 3 2 1 0         这里是索引的位置
        //0 0 0 0 0 0 0 0         这里是第一个字节数组存放的0还是1

        //15 14 13 12 11 10 9 8   这里是索引的位置
        //0  0  0  0  0  0  0 0   这里是第二个字节数组存放的0还是1
        //获取新的元素要左移的位置
        //num%8表示10%8=2 表示右边距离的位置
        //7是下标最后一位,左边减去右边,就是15那个位置要往右移动到10的位置
        int zy=7-(num%8);
        //从左往右走 和之前的数据取余
        //如果都是1,那么才是1,如果有1个0,都是0,那么数组中不存在
        return (b&1<<zy)!=0;
    }

}
package com.example.demo.mapper;

import com.example.demo.entity.BitMap;

import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

public class Test {

    public static void main(String[] args) {
        BitMap bitMap=new BitMap(999999999);
        bitMap.set(666);
        bitMap.set(777);
        bitMap.set(888);
        System.out.println(bitMap.get(222));
        System.out.println(bitMap.get(333));
        System.out.println(bitMap.get(666));
        System.out.println(bitMap.get(777));
        System.out.println(bitMap.get(888));

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值