`
什么世道
  • 浏览: 219323 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

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

阅读更多

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

    问题提出: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);
                }
            }
        }
    }
}

 

 

 

  • 大小: 39.1 KB
4
1
分享到:
评论
9 楼 chenzehe 2013-11-06  
mark支持下
8 楼 什么世道 2013-11-06  
fourfireliu 写道
youtl 写道
将这么大的数据读到内存中,是不合理的。删除重复数据可以借鉴压缩的原理。
建一个对象{int first,int num},为了节约空间,用int[2]存储就行。然后用有序二叉树保存起来。比如[5,3]表示5,6,7三个数。
当你从文件中读出一个int,就在二叉树中查找是否存在当前数字,如果有的话就去掉,如果没有的话,再判断是否能跟上界以及下界压缩保存,不能的话,才需要将它存储起来。

它这个一样可以分段存文件最后考虑压缩 不见得非要2叉树

分段排序存文件可能是一个比较理想的方式,占用内存可以非常少。时间上全部读入内存可能快一点。在时间和空间上找个平衡吧。
7 楼 fourfireliu 2013-11-06  
youtl 写道
将这么大的数据读到内存中,是不合理的。删除重复数据可以借鉴压缩的原理。
建一个对象{int first,int num},为了节约空间,用int[2]存储就行。然后用有序二叉树保存起来。比如[5,3]表示5,6,7三个数。
当你从文件中读出一个int,就在二叉树中查找是否存在当前数字,如果有的话就去掉,如果没有的话,再判断是否能跟上界以及下界压缩保存,不能的话,才需要将它存储起来。

它这个一样可以分段存文件最后考虑压缩 不见得非要2叉树
6 楼 fourfireliu 2013-11-06  
我记得这是编程珠矶里的例子 不过lz把它用java实现了
5 楼 youtl 2013-11-06  
不好意思,没有代码。如果要保存在磁盘中,可以从树中读取,也就是说数据是根据树的结果去生成。
其实int[2]的压缩方式还是压缩率不够高的,如果是long类型的话,也不见得吃的消。如有必要还可以引入byte[2]数组之类的,沿着这条路进行下去,总有办法解决long的排序问题,只是代码估计就复杂了。但你用的方法,就只能解决int类型的。而且jvm内存占用也不低,jvm是没办法使用电脑所有内存的。
还有一个有效的方法,是对数字进行分段加载,将未处理的数字,用硬盘先存储起来。
4 楼 9344187 2013-11-06  
youtl 写道
将这么大的数据读到内存中,是不合理的。删除重复数据可以借鉴压缩的原理。
建一个对象{int first,int num},为了节约空间,用int[2]存储就行。然后用有序二叉树保存起来。比如[5,3]表示5,6,7三个数。
当你从文件中读出一个int,就在二叉树中查找是否存在当前数字,如果有的话就去掉,如果没有的话,再判断是否能跟上界以及下界压缩保存,不能的话,才需要将它存储起来。


请问采用二叉树的方式,怎样让数据保存在磁盘中呢?有相应的代码参考一下吗?
3 楼 zhangyan19870108 2013-11-05  
lz思路很好
2 楼 zhangyan19870108 2013-11-05  
1 楼 youtl 2013-11-05  
将这么大的数据读到内存中,是不合理的。删除重复数据可以借鉴压缩的原理。
建一个对象{int first,int num},为了节约空间,用int[2]存储就行。然后用有序二叉树保存起来。比如[5,3]表示5,6,7三个数。
当你从文件中读出一个int,就在二叉树中查找是否存在当前数字,如果有的话就去掉,如果没有的话,再判断是否能跟上界以及下界压缩保存,不能的话,才需要将它存储起来。

相关推荐

    numpy数据分析源代码+大数据的读取_.ipynb

    详细的,有解释的源代码哦 pandas数据处理 1、删除重复元素 使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True ...大数据读取

    大数据导论-6.1.4-熟悉大数据处理技术——大数据的处理模式.pptx

    当前的软件实现是指定一个Map(映射)函数,用来把一组键值对映射成一组新的键值对,指定并发的Reduce(归约)函数,用来保证所有映射的键值对中的每一个共享相同的键组。 大数据导论-6全文共20页,当前为第4页。 ...

    大数据面试题(2).docx

    s、对这10个文件进行归并排序(内排序与外排序相结合)。 方案2: 一般query的总量是有限的,只是重复的次数比较多而已,可能对于所有的query,一次性就可以加入到内存了。这样,我们就可以采用trie树/hash_map等...

    大数据调研报告(多篇).docx

    非结构化信息——该信息在本质形式上可认为主要是位映射数据。数据必须处于一种可感知的形式中(诸如可在音频、视频和多媒体文件中被听或被看)。许多大数据都是非结构化的,其庞大规模和复杂性需要高级分析工具来...

    几道大数据面试题.pdf

    Step3:把这5000个⽂件进⾏归并(类似与归并排序); 草图如下(分割⼤问题,求解⼩问题,归并): 3. 现有海量⽇志数据保存在⼀个超级⼤的⽂件中,该⽂件⽆法直接读⼊内存,要求从中提取某天出访问百度次数最多的...

    大数据的一些面试题.pdf

    七、倒排索引(Inverted index) 适⽤范围:搜索引擎,关键字查询 基本原理及要点:为何叫倒排索引?⼀种索引⽅法,被⽤来存储在全⽂搜索下某个单词在⼀个⽂档或者⼀组⽂档中的存储位置的映射。 以英⽂为例,下⾯是要...

    大数据时代下的数据挖掘试题及答案.doc

    估计遗漏值 8) 假设12个销售价格记录组已经排序如下:5, 10, 11, 13, 15, 35, 50, 55, 72, 92, 204, 215 使用如下每种方法将它们划分成四个箱。等频(等深)划分时,15在第几个箱子内? (B) A。第一个 B。第二个 ...

    《大数据时代下的数据挖掘》试题及答案.doc

    估计遗漏值 8) 假设12个销售价格记录组已经排序如下:5, 10, 11, 13, 15, 35, 50, 55, 72, 92, 204, 215 使用如下每种方法将它们划分成四个箱。等频(等深)划分时,15在第几个箱子内? (B) A.第一个 B。第二个...

    云数据库方案设计(1).doc

    与大数据存储平台的数据集成 数据库提供外部表技术,可以将交易型和分析型数据库与其他存储平台对接,在数 据库内部,通过外部表访问大数据存储平台中的数据,包括: a)与HDFS对接:外部表访问引擎(读写模块),...

    云数据库方案设计.doc

    与大数据存储平台的数据集成 数据库提供外部表技术,可以将交易型和分析型数据库与其他存储平台对接,在数 据库内部,通过外部表访问大数据存储平台中的数据,包括: a)与HDFS对接:外部表访问引擎(读写模块),...

    云数据库方案设计.docx

    大数据计算平台,例如Spark、HIVE等,需要支持大数据计算平台与数据库互访。以大数据计算平台为中心,建立分析平台。 云数据库方案设计全文共6页,当前为第4页。 大数据计算平台访问数据库 a)大数据计算平台Spark: ...

    nosql 入门教程

    4.1.3 列数据库当做键/值对的嵌套映射表 67 4.1.4 Webtable布局 70 4.2 HBase分布式存储架构 71 4.3 文档存储内部机制 73 4.3.1 用内存映射文件存储数据 74 4.3.2 MongoDB集合和索引使用指南 75 4.3.3 MongoDB...

    react-dynamic-data-table:具有可排序列、分页等功能的 React 可重用数据表

    React动态数据表 这个包提供了一个 React 动态数据表组件,支持可排序的列、分页、字段映射、数据操作等。安装您可以使用npm或yarn安装此包,如下所示。 npm install @langleyfoxall/react-dynamic-data-tableyarn ...

    FruitCount:通过MapReduce程序从输入文件计算“苹果”,“香蕉”和“葡萄”的出现频率

    映射过程:执行过滤和排序。 减少方法:执行摘要操作。 驱动程序类驱动程序类是控制程序执行的主要类。 在这里,我们创建一个Job对象,并设置程序中使用的驱动程序,映射程序和reducer类。 Mapper类MapReduce...

    基于Python的中文本关键词抽取源码(分别使用TF-IDF、TextRank、Word2Vec词聚类三种方法).zip

    2.主要针对各个计算机相关专业,包括计算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网等领域的在校学生、专业教师、企业员工。 3.项目具有丰富的拓展空间,不仅可作为入门进阶,也可直接作为...

    快学 scala 中文版 带完整目录

    4.5 已排序映射 57 4.6 与Java的互操作 57 4.7 元组 58 4.8 拉链操作 59 练习 60 第5章 类 A1 63 5.1 简单类和无参方法 63 5.2 带getter和setter的属性 64 5.3 只带getter的属性 67 5.4 对象私有字段 68 ...

    scala从入门到精通技术教学视频

    07.位运算符 08.案例_交换变量值 第四章 流程控制结构 00.导学 01.流程控制结构之顺序结构 02.选择结构之单分支结构 03.选择结构之双分支结构 04.选择结构之多分支结构 05.选择结构之注意事项 06.选择结构之嵌套...

    全文检索使用ElasticSearch实现全文检索的详细说明和实践探索

    可以通过使用ElasticSearch提供的API来创建索引、定义映射(Mapping)以及导入数据。 执行搜索: 通过ElasticSearch的RESTful API执行搜索操作。可以使用各种查询语句,如match、term、bool等,来构建搜索条件。 ...

    Hadoop HBase数据库简介

    HBase 和传统关系数据库不同,它采用了 BigTable 的数据模型增强的稀疏排序映射表(Key/Value ),其中,键由行关键字、列关键字和时间戳构成。 HBase 提供了对大规模数据的随机、实时读写访问。HBase 的目标是存储...

Global site tag (gtag.js) - Google Analytics