位映射对大数据排重与排序

2024-06-08 19:48

本文主要是介绍位映射对大数据排重与排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

利用位映射原理对大数据排重

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

 

    问题分析:我们肯定会先想到在计算机内存中开辟M个int整型数据数组,来one bye one读取M个int类型数组, 然后在一一比对数值,最后将重复数据的去掉。当然这在处理小规模数据是可行的。

            

我们 考虑大数据的情况:例如在java语言下,对10亿个int类型数据排重。

 

java中一个 int 类型在内存中占4 byte。那么10亿个int类型数据共需要开辟10 ^ 9次方 *4 byte ≈ 4GB 的连续内存空间。以 32 位操作系统电脑为例,最大支持内存为 4G, 可用内存更是小于4G。所以上述方法在处理大数据时根本行不通。

 

    思维转化:既然我们不能为所有 int 类型的数据开辟 int 类型数组,那么可以采取更小的数据类型来读取缓存 int 类型数据。考虑到计算机内部处理的数据都是 01 序列的bit,那么我们是否可以用 1bit 来表示一个 int 类型数据。

 

   位映射的引出:使用较小的数据类型指代较大的数据类型。如上所说的问题,我们可以用1个 bit 

来对应一个int 整数。假如对应的 int 类型的数据存在,就将其对应的 bit 赋值为1,否则,赋值为0(boolean类型)。java中 int 范围为 -2^31  到  2^31-1. 那么所有可能的数值组成的长度为2^32. 对应的 bit 长度也为 2^32.  那么可以用这样处理之后只需要开辟2^32 bit  = 2^29 byte = 512M 大小的 内存空间 。显然,这样处理就能满足要求了。虽然对内存的消耗也不太小,暂时这样处理吧。

 

   问题解决方案: 首先定义如下图的int - byte 映射关系,当然,映射关系可以自定义。但前提要保证你的数组上下标不能越界。

 

 



 

但如上定义的bit[]数组显然在计算机中是不存在的,所我们需要将其转化为 java 中的一个基本数据类型存储。显然,byte[] 是最好的选择。

 

将其转化为byte[] 数组方案:

自定义的映射关系表,每个bit对应一个 int 数值,鄙人将 int 的最大值,最小值与数组的最大最小索引相对应。从上图可以看出来 int 数值与bit索引相差 2^31次方。当然,你也可以定义其他的映射关系,只是注意不要发生数组越界的情况。由于最大值可能是2^32,故用long接收。

long bitIndex = num + (1l << 31);

 

计算在转化为byte[]数组的索引,由于上面定义的bitIndex 索引是非负数,故无需引入位运算去符号。

 int index = (int) (bitIndex / 8); 

 

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

 int innerIndex = (int) (bitIndex % 8);

 

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

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

 

这样就解决了整个大数据读取排重的问题。

 

那么怎么将其读取出来呢?怎么对数据进行排序?

 

那就只需要按照byte[]数组进行一一对应到 int 类型数据上即可。

以下代码升序输出为例。

 

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

 

 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)));

                }

            }

        } 

 }

 

 

由于编译软件默认设置的JVM内存是128—400M左右,测试此程序明显是不够的,所以需要调节一下分配给JVM的内存。否则,不管怎样运行,都会出现Exception in thread "main" java.lang.OutOfMemoryError: Java heap space...

 

eclipse:选择run->run configuration->arguments,输入-Xms256M -Xmx1024M(-Xms代表jvm启动时分配的内存大小,-Xmx代表可最大分配多少内存)

Intellij IDEA修改安装目录/IntelliJ IDEA 7.0/bin下idea.exe.vmoption文件 

    -Xms256M 
    -Xmx1024M 
  
    

 

 

源代码:

 

package com.MassSort20131103;import java.util.Random;/*** Created with IntelliJ IDEA.* User: YangKang* Date: 13-11-3* Time:上午11:32* To change this template use File | Settings | File Templates.*/
public class BigDataSort {private static final int CAPACITY = 1 000 000 000;//数据容量// 定义一个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数组* @param num 读取的数据* @return byte数组  dataBytes*/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;}/*** 输出数组中的数据* @param bytes byte数组*/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);}}}}
}

 

 

 

这篇关于位映射对大数据排重与排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1043143

相关文章

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Java枚举类实现Key-Value映射的多种实现方式

《Java枚举类实现Key-Value映射的多种实现方式》在Java开发中,枚举(Enum)是一种特殊的类,本文将详细介绍Java枚举类实现key-value映射的多种方式,有需要的小伙伴可以根据需要... 目录前言一、基础实现方式1.1 为枚举添加属性和构造方法二、http://www.cppcns.co

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

Python Dash框架在数据可视化仪表板中的应用与实践记录

《PythonDash框架在数据可视化仪表板中的应用与实践记录》Python的PlotlyDash库提供了一种简便且强大的方式来构建和展示互动式数据仪表板,本篇文章将深入探讨如何使用Dash设计一... 目录python Dash框架在数据可视化仪表板中的应用与实践1. 什么是Plotly Dash?1.1

Redis 中的热点键和数据倾斜示例详解

《Redis中的热点键和数据倾斜示例详解》热点键是指在Redis中被频繁访问的特定键,这些键由于其高访问频率,可能导致Redis服务器的性能问题,尤其是在高并发场景下,本文给大家介绍Redis中的热... 目录Redis 中的热点键和数据倾斜热点键(Hot Key)定义特点应对策略示例数据倾斜(Data S

Python实现将MySQL中所有表的数据都导出为CSV文件并压缩

《Python实现将MySQL中所有表的数据都导出为CSV文件并压缩》这篇文章主要为大家详细介绍了如何使用Python将MySQL数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到... python将mysql数据库中所有表的数据都导出为CSV文件到一个目录,并压缩为zip文件到另一个

SpringBoot整合jasypt实现重要数据加密

《SpringBoot整合jasypt实现重要数据加密》Jasypt是一个专注于简化Java加密操作的开源工具,:本文主要介绍详细介绍了如何使用jasypt实现重要数据加密,感兴趣的小伙伴可... 目录jasypt简介 jasypt的优点SpringBoot使用jasypt创建mapper接口配置文件加密

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解