JAVA海量数据处理之二(BitMap)

    路漫漫其修远兮,吾将上下而求索。想要更快,就要深入挖掘 JAVA 基础的数据结构,从来分析出所编写的 JAVA 代码为什么把内存耗尽,思考有什么办法可以节省内存呢? 啊哈!算法。这里采用了 BitMap 思想。

 

首先来看一个实验:

指定 VM 参数大小: -Xms256m -Xmx540m

 

Java代码
  1. import java.util.TreeSet;   
  2.   
  3. public class Test {   
  4.   
  5.     public static void main(String[] args) {   
  6.   
  7.        TreeSet set = new TreeSet();   
  8.   
  9.        for(long i=10000000000L;i<900000000000L;i++){   
  10.   
  11.            set.add(i);   
  12.   
  13.            System.out.println("i="+i);   
  14.   
  15.        }   
  16.   
  17.     }   
  18.   
  19. }  
import java.util.TreeSet;public class Test {    public static void main(String[] args) {       TreeSet set = new TreeSet();       for(long i=10000000000L;i<900000000000L;i++){           set.add(i);           System.out.println("i="+i);       }    }}
 

一个简单的 FOR 循环,运行该类,可以看到当输出: i=10011703526 的时候报错了

 

Java代码
  1. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space  
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
 

如果把上面的例子中的   set.add(i);  修改成 set.add(i+"");    那结果又是什么呢?

当输出 i=10005851762 时报了同样的错,内存溢出。为什么往内存里放 Long 型的比 String 型的多了近一半的数据呢?

 

Java代码
  1. 1024 个字节 =1KB , 1024KB=1MB , 1024MB=1GB   
1024 个字节 =1KB , 1024KB=1MB , 1024MB=1GB 

 

 

Long 占 8 个字节 (64 位 ) , 11703526 个 Long 型数据约 91433KB  合 89M

String 内部是由 char 构成,一个 char 占 2 个字节, 11 位的数据是 22 个字节, 5851762 个 String 型数据 约合 125721KB 合 122M

11 位的 String 数据比 11 位的 Long 型数据要占内存多。

 

总结:内存溢出是由于自己没有做到节省内存,用 64 位的 Long 型数据或 176 位的 String 型数据来存储 11 位的数据。那能不能用内存里的 11 位即 11bit 来表示 11 位数据呢?

 

还是上一章(《 JAVA 海量数据处理之一》)的问题,我还能再快吗?答案是可以的!

我在编码中改用了 BitMap 思想,使效率又提升了一倍。

 

【什么是Bit-map 】

 

所谓的Bit-map 就是用一个bit 位来标记某个元素对应的Value , 而Key 即是该元素。由于采用了Bit 为单位来存储数据,因此在存储空间方面,可以大大节省。

详细资料可参考:

http://blog.csdn.net/hit_kongquan/article/details/6255673

http://wansishuang.appspot.com/?p=35003

 

例子:用位向量来表示数据: 1 、 3 、 6 、 10 、 100

 

Java代码
  1. import java.util.BitSet;   
  2.   
  3. public class BitTest {   
  4.   
  5.     public static void main(String[] args) {   
  6.   
  7.        // 1 3 6 10 100   
  8.   
  9.          BitSet bitSet = new BitSet(100);   
  10.   
  11.          bitSet.set(1,true);   
  12.   
  13.          bitSet.set(3,true);   
  14.   
  15.          bitSet.set(6,true);   
  16.   
  17.          bitSet.set(100,true);   
  18.   
  19.          for(int i=0;i<bitSet.size();i++){   
  20.   
  21.          boolean b = bitSet.get(i);   
  22.   
  23.          if(b){   
  24.   
  25.               System.out.println(i);   
  26.   
  27.          }   
  28.   
  29.          }   
  30.   
  31.     }   
  32.   
  33. }  
import java.util.BitSet;public class BitTest {    public static void main(String[] args) {       // 1 3 6 10 100         BitSet bitSet = new BitSet(100);         bitSet.set(1,true);         bitSet.set(3,true);         bitSet.set(6,true);         bitSet.set(100,true);         for(int i=0;i<bitSet.size();i++){         boolean b = bitSet.get(i);         if(b){              System.out.println(i);         }         }    }}
 

用 BitMap 来实现数据过滤结果:

 

Java代码
  1. * 371M 的文件( 3000 万的数据)   过滤数据耗时 : 27375 毫秒   
  2.   
  3. * 520M 的文件( 4200 万的数据)   过滤数据耗时 : 62000 毫秒   
      * 371M 的文件( 3000 万的数据)   过滤数据耗时 : 27375 毫秒      * 520M 的文件( 4200 万的数据)   过滤数据耗时 : 62000 毫秒 

 其中把 4200 万的数据用 BitSet 操作耗时约 20-30 秒,写入目标文件约 30 秒。所以 1 分钟可以搞定 4200 万的数据。效率已经得到了极大的提高。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值