文章目录

  • 一、问题提出
  • 二、问题分析
  • 三、位映射的详细阐述
  • 四、将int[] 数组转化为byte[] 数组方案
    • 4.1 实现bit索引与int数值之间的映射关系
    • 4.2 计算转化为byte[]数组的索引
    • 4.3 计算bitIndex在byte[]数组索引index中的具体位置
    • 4.4 引入位运算将byte[] 数组索引index 的各个位按权值相加
  • 五、读取byte[] 数组以及对其排序
    • 5.1 读取byte[]数组
    • 5.2 完整源码

一、问题提出

M(比如有10亿)个int整数,只有其中N个数重复出现过,读取至内存中并将重复的整数删除。

二、问题分析

首先,我们肯定会想到在计算机内存中开辟M个int型数据数组,然后一个一个地读取M个int类型数组,然后一个一个进行比较其数值,最后将其重复的数据去掉。当然,这的确是一种方法,但是当M的值等于10亿时,像这么庞大的数据时,计算机是处理不过来的。

我们可以Java语言为例,在Java中一个int 类型在内存中占4 byte,那么10亿个int 类型的数据则需要开辟10亿 * 4byte 约等于 4GB的连续内存空间。如果我们的电脑是32位操作系统,最大支持内存为4G,但可用内存更是小于4G,所以,从这个理论层面上来讲,直接一个一个地去读取10亿个整型数据是不现实的,根本行不通的。但是,从现实层面来讲,我们知道我们的计算机的确能够去处理这10亿的数据排序与排重的,难道是我们的理论分析错了???其实不然,既然从现实的层面来讲,计算机是能够处理这10亿个数据的,说明计算机的内部肯定做了哪些变换,使得计算机面对这么庞大的数据集时能够很好的进行排序与排重的。

是的,在计算机内部的确做了一些转换,既然我们知道不能为所有的int 类型的数据开辟int 类型的数组,但是我们可以采用更小的数据类型来读取缓存的int 类型的数据。考虑到计算机内部处理的数据都是01序列的bit,那么我们就能够用1bit来表示一个int 类型的数据。这样就有了"位映射"这个概念,当我们用自己的电脑处理这么庞大的数据时,基本上都会采用这样的一种处理数据的思想,即将需要处理的数据转换为最小的处理单位bit来代替处理。

三、位映射的详细阐述

正如上述的问题分析,我们知道可以用一个bit来对应一个int整数。假如,在10亿个int类型数据中,每一个int类型的数据都使之对应位置的的bit赋值为1,比如,在这10亿个int类型的数据中,其中有个数的int值为98,则在bit的第98个位置标为1,以此类推,一一对应,如果存在两个或者多个98的这个数,则就能将其返回,实现排重的功能。

实现这样的一个一一映射的关系,就会发现我们只需要对应得bit长度为2的32次方,然后换算一下2的32次方bit等于2的29次方byte = 512M大小的内存空间,显然,通过这样的映射处理,再来对10亿个数据进行排序与排重就不是什么大问题了。下面是一张int - bit映射关系图。

但是,在Java语言,我们输入bit[] 数组时,代码是会报错的,因为在计算机中bit[] 数组是不存在的,所以我们将其转换为byte[] 数组,这是一个Java中的一个基本数据类型。

四、将int[] 数组转化为byte[] 数组方案

4.1 实现bit索引与int数值之间的映射关系

因为每一个bit对应一个int数值,一般习惯将映射关系设置为int的最大值、最小值与数组的最大最小索引相对应,如上图,int 数值与bit 索引相差2的31次方,故

long bitIndex = num + (1l << 31) //表示bit索引bitIndex与int数值num之间的关系,获取num数据对应bit数组的索引值

4.2 计算转化为byte[]数组的索引

由于上面定义的bitIndex索引是非负数,故就能够计算出byte数组的索引值

int index = (int)(bitIndex / 8); //获取int型的数值是属于byte数组中的哪一个组的

4.3 计算bitIndex在byte[]数组索引index中的具体位置

int innerIndex = (int)(bitIndex % 8); //获取在index中的具体位置

4.4 引入位运算将byte[] 数组索引index 的各个位按权值相加

dataBytes[index] = (byte)(dataBytes[index]|(1 << innerIndex));

五、读取byte[] 数组以及对其排序

5.1 读取byte[]数组

遍历数组,采取与之前映射关系的逆运算来还原数据

for(int i=0; i<bytes.length; i++){for(int j=0; j<8; j++){if(!(((bytes[i]) & (1 << j)) == 0)){int number = (int)((((long)i * 8 + j)-(1l << 31)));}}
}

5.2 完整源码

由于编译软件默认设置的JVM内存是128-400M左右,测试该程序是明显不够的,所以需要调节一下JVM的内存,否则,不管怎样运行,都会出现Exception in thread “main” java.lang.OutOfMemoryError: Java heap space…,但是现在的电脑都是64位的,因此该内存完全够用了,如果电脑还是32位的,则需要做以下的修改。

eclipse:选择run->run configuration->arguments,输入-Xms256M -Xmx1024M(-Xms代表jvm启动时分配的内存大小,-Xmx代表可最大分配多少内存)Intellij IDEA:修改安装目录/IntelliJ IDEA 7.0/bin下idea.exe.vmoption文件 -Xms256M -Xmx1024M

源码如下:

package com.company;import java.util.Random;public class BigDataSort {public static final  int CAPACITY = 1000; //数据的容量//定义一个byte数组缓存所有的数据private byte[] dataBytes = new byte[1 << 29];public static void main(String[] args) {BigDataSort ms = new BigDataSort();byte[] bytes = null;Random random =new Random();for(int i = 0; i < CAPACITY; i++){int num = random.nextInt();System.out.println("读取了第"+(i+1)+"\t个数"+num);bytes = ms.splitBigData(num);}System.out.println("");ms.output(bytes);}/** 读取数据,并将对应数据对应到bit中,并返回byte数组中** */private byte[] splitBigData(int num){long bitIndex = num + (1l << 31); //获取num数据对应bit数组索引int index = (int)(bitIndex / 8); //bit数组在byte数组中的索引int innerIndex = (int)(bitIndex % 8); //bitIndex在byte[]数组索引index中的具体位置System.out.println("byte["+index+"]中的索引:"+ innerIndex);dataBytes[index] = (byte)(dataBytes[index] | (1 << innerIndex));return dataBytes;}/** 输出数组中的数据** */private void output(byte[] bytes){int count = 0;for (int i = 0; i < bytes.length; i++){for(int j = 0; j < 8; j++){if(!(((bytes[i]) & (1 << j)) == 0)){count++;int number = (int)((((long)i * 8 + j) - (1l << 31)));System.out.println("取出的第" + count + "\t个数:" + number);}}}}
}

欢迎浏览我的个人博客:https://chasing987.github.io/2020/12/12/%E4%BD%8D%E6%98%A0%E5%B0%84%E8%A7%A3%E5%86%B3%E5%A4%A7%E6%95%B0%E6%8D%AE%E6%8E%92%E5%BA%8F%E4%B8%8E%E6%8E%92%E9%87%8D%E9%97%AE%E9%A2%98/

位映射--解决大数据排序与排重问题相关推荐

  1. 数据结构与算法 第八天常见排序+冒泡排序+快速排序+文件IO+大数据排序+文件合并

    数据结构与算法 第八天常见排序+冒泡排序+快速排序+文件IO+大数据排序+文件合并 第一章 冒泡排序 [1]Bubble_Sort.c 第二章 快速排序 [1]quick_sort.c 第三章 大数据 ...

  2. 面试精讲之面试考点及大厂真题 - 分布式专栏 17 ElasticSearch解决大数据量检索难题

    17 ElasticSearch解决大数据量检索难题 理想的书籍是智慧的钥匙. --列夫·托尔斯泰 引言 如果你的项目里有超过千万上亿级别的数据,且数据日增量较大需要高性能检索时,如订单数据,你该怎么 ...

  3. MERGE INTO 解决大数据量 10w 更新缓慢的问题

    MERGE INTO 解决大数据量 10w 更新缓慢的问题 参考文章: (1)MERGE INTO 解决大数据量 10w 更新缓慢的问题 (2)https://www.cnblogs.com/yun9 ...

  4. Apache Mnemonic成为Apache顶级项目,主要解决大数据性能问题

    近日,Apache软件基金会宣布,Apache Mnemonic从Apache孵化器中毕业成为顶级项目. Apache Mnemonic是一个用于处理和分析链接对象的开源对象平台,旨在解决大数据性能问 ...

  5. 大数据 就业 缺口_三年培养10万大数据人才,解决大数据人才缺口

    (原标题:三年培养10万大数据人才,解决大数据人才缺口) 未来三年为中国培养10万大数据人才,大数据人才优选计划缓解中国大数据人才缺口 为缓解中国大数据人才缺口,小牛学堂联合工信部人才交流中心,开展& ...

  6. FOR ALL ENTRIES IN内表排序、排重对性能的影响

    大家都知道for all entries in 关联内表时,要先判断内表不为空 否则会扫描全表,非常消耗服务器内存资源,那么内表关键字段的排序和排重对查询效率有没有影响呢?下面看一个例子 程序代码: ...

  7. php数组操作之合并相同键名的值,排序,排重,去空值等

    一.前言 数组操作是咱们在编程时候经常遇到的,只是数组函数有点多,用到的时候难免会想不起来.特别是针对多维数组的操作,有的时候用自带的数组函数真的很方便,可以避免多次的foreach循环,这里记录一下 ...

  8. 内存不够解决大数据问题

    在研究.应用机器学习算法的经历中,相信大伙儿经常遇到数据集太大.内存不够用的情况. 这引出一系列问题: 怎么加载十几.几十 GB 的数据文件? 运行数据集的时候算法崩溃了,怎么办? 怎么处理内存不足导 ...

  9. jquery数据折叠_通过位折叠缩小大数据

    jquery数据折叠 Sometimes your dataset is just too large, and you need a way to shrink it down to a reaso ...

最新文章

  1. 剑指Offer_08_跳台阶
  2. volatile关键字——保证并发编程中的可见性、有序性
  3. Oracle中的正则表达式(REPLACE 和REGEXP_REPLACE)---转载自http://database.51cto.com/art/201009/228270.htm...
  4. 机器学习算法概述:随机森林逻辑回归
  5. rfc方式的集成 sap_转载: 与SAP集成的接口方式比较:IDOC BAPI RFC 之间的区别
  6. Excel2007数据透视表学习(一)
  7. ACCESS实例1——简易文档管理器
  8. 流畅的python不适合初学者_学习《流畅的python》第一天
  9. Android之Canvas撕衣服
  10. 新机购入 戴尔成就5000
  11. 《视觉SLAM十四讲-第二版-ch8,OpenCV4报错及解决》
  12. java练手代码大全手机版_Java版打字练习游戏源码
  13. magento 为用户注册增加一个字段
  14. [RK3399][Android7.1] 调试笔记 --- Audio codec时钟源从BCLK1获取
  15. 计算机系统集成及运维,信息系统集成资质取消!ITSS或将取代其招投标地位!...
  16. 输入数字的汉语拼音,每个拼音的首字母大写。输出该数字的阿拉伯数字。
  17. PHPSTORM取消提示变量的黄色下滑波浪线
  18. python dataframe dropna_在Python中使用熊猫在两个DataFrame之间进行值...
  19. 小小二维码,引领大数据时代,爱码物联一物一码功能解析!
  20. EventBus基础

热门文章

  1. 计算机c语言循环作业,C语言计算机作业编程.doc
  2. php删除所以文件,php如何删除所有文件
  3. sql mysql 删除数据库_在sql中将已建数据库删除的详细步骤
  4. android网络请求框架_2020,最新APP重构:网络请求框架
  5. java org.jb2011报错_Java中getResourceAsStream()用法总结(转)
  6. linux压缩图片脚本,说明Ubuntu压缩图片脚本批量方法
  7. liferay7.0 mysql_Liferay7 BPM门户开发之6: Activiti数据库换为mysql
  8. php读取文件内容不全,php读取文件内容的三种方法
  9. everything每次打开都会扫描_每次启动车,转方向盘都会咔一下,咋回事?
  10. brave浏览器_兼容Chrome 插件的Brave浏览器,带给你更快速的上网冲浪体验