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

标签: 映射 大数据 排序 | 发表时间:2013-11-05 00:37 | 作者:
出处:http://www.iteye.com

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

    问题提出: 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. 那么所有可能的数值组成的长度为2^32. 对应的 bit 长度也为 2^32.   那么可以用这样处理之后只需要开辟 2^32 bit  = 2^29 byte = 512M 大小的  内存空间 。显然,这样处理就能满足要求了。虽然对内存的消耗也不太小,暂时这样处理吧。

 

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

 

 



 

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

 

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

自定义的映射关系表,注意数组越界的情况。由于最大值可能是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 = Integer.MAX_VALUE;

    // 定义一个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);    //获取 bit 数组的数据

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

 

 

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [映射 大数据 排序] 推荐:

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

- - ITeye博客
利用位映射原理对大数据排重.     问题提出: M (如 10亿 )个int整数,只有其中N个数重复出现过,读取到内存中并将重复的整数删除.     问题分析: 我们肯定会先想到在计算机内存中开辟M个int整型数据数组,来one bye one读取M个int类型数组, 然后在一一比对数值,最后将重复数据的去掉.

大数据排序或取重或去重相关问题

- - 学着站在巨人的肩膀上
给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,让你找出a、b文件共同的url. 方案1:可以估计每个文件安的大小为50G×64=320G,远远大于内存限制的4G. 所以不可能将其完全加载到内存中处理. s 遍历文件a,对每个url求取 ,然后根据所取得的值将url分别存储到1000个小文件(记为 )中.

MVC框架的映射和解耦

- - 博客 - 伯乐在线
最近在写一个业务上用到的框架,回想起接触过的一些MVC框架,尤其是主要贡献在后端表现层上的那些,它们之间有太多的相似,在不断解耦的过程中,层数和模块数也越来越多,需要不断引入层与层之间的映射逻辑将不同层次之间关联起来,我们不妨来查看一下这个过程,能否寻找一些MVC框架的共性和启示. MVC 1到MVC 2模型的进化.

JPA基本数据类型映射

- - 编程语言 - ITeye博客
                // initialValue = 0, allocationSize = 1)   Oracle中序列方式生成主键.                 //Oracle序列方式生成/主键.                 @GeneratedValue(strategy = GenerationType.IDENTITY)   //MySQL,SQLSErver自增长方式.

hibernate 大对象类型的hibernate映射

- - CSDN博客推荐文章
在 Java 中, java.lang.String 可用于表示长字符串(长度超过 255), 字节数组 byte[] 可用于存放图片或文件的二进制数据. 此外, 在 JDBC API 中还提供了 java.sql.Clob 和 java.sql.Blob 类型, 它们分别和标准 SQL 中的 CLOB 和 BLOB 类型对应.

谈大数据(2)

- - 人月神话的BLOG
对于大数据,后面会作为一个系列来谈,大数据涉及的方面特别多,包括主数据,数据中心和ODS,SOA,云计算,业务BI等很多方面的内容. 前面看到一个提法,即大数据会让我们更加关注业务方面的内容,而云平台则更多是技术层面的内容. 对于大数据会先把各个理解的关键点谈完了,再系统来看大数据的完整解决方案和体系化.

大数据之惑

- - 互联网分析
算起来,接触大数据、和互联网之外的客户谈大数据也有快2年了. 也该是时候整理下一些感受,和大家分享下我看到的国内大数据应用的一些困惑了. 云和大数据,应该是近几年IT炒的最热的两个话题了. 在我看来,这两者之间的不同就是: 云是做新的瓶,装旧的酒; 大数据是找合适的瓶,酿新的酒. 云说到底是一种基础架构的革命.

白话大数据

- - 互联网分析
这个时代,你在外面混,无论是技术还是产品还是运营还是商务,如果嘴里说不出“大数据”“云存储”“云计算”,真不好意思在同行面前抬头. 是千万级别的用户信息还是动辄XXXTB的数据量. 其实,大数据在我的眼里,不是一门技术,而是一种技能,从数据中去发现价值挖掘价值的技能. ”当我掷地有声用这句话开场时,正好一个妹子推门而入,听到这句话,微微一怔,低头坐下.

交通大数据

- - 人月神话的BLOG
本文简单谈下智慧交通场景下可能出现的大数据需求和具体应用价值. 对于公交线路规划和设计是一个大数据潜在的应用场景,传统的公交线路规划往往需要在前期投入大量的人力进行OD调查和数据收集. 特别是在公交卡普及后可以看到,对于OD流量数据完全可以从公交一卡通中采集到相关的交通流量和流向数据,包括同一张卡每天的行走路线和换乘次数等详细信息.

堆排序

- kongshanzhanglao - 博客园-首页原创精华区
       堆排序是利用堆的性质进行的一种选择排序.   堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:.   Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2].   即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字.