JAVA海量数据处理之二(BitMap)
2012-06-26 13:06
302 查看
路漫漫其修远兮,吾将上下而求索。想要更快,就要深入挖掘 JAVA 基础的数据结构,从来分析出所编写的 JAVA 代码为什么把内存耗尽,思考有什么办法可以节省内存呢? 啊哈!算法。这里采用了 BitMap 思想。
首先来看一个实验:
指定 VM 参数大小: -Xms256m -Xmx540m
Java代码
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代码
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
如果把上面的例子中的 set.add(i); 修改成 set.add(i+""); 那结果又是什么呢?
当输出 i=10005851762 时报了同样的错,内存溢出。为什么往内存里放 Long 型的比 String 型的多了近一半的数据呢?
Java代码
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代码
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代码
* 371M 的文件( 3000 万的数据) 过滤数据耗时 : 27375 毫秒
* 520M 的文件( 4200 万的数据) 过滤数据耗时 : 62000 毫秒
其中把 4200 万的数据用 BitSet 操作耗时约 20-30 秒,写入目标文件约 30 秒。所以 1 分钟可以搞定 4200 万的数据。效率已经得到了极大的提高。
首先来看一个实验:
指定 VM 参数大小: -Xms256m -Xmx540m
Java代码
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);
}
}
}
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代码
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代码
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代码
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);
}
}
}
}
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代码
* 371M 的文件( 3000 万的数据) 过滤数据耗时 : 27375 毫秒
* 520M 的文件( 4200 万的数据) 过滤数据耗时 : 62000 毫秒
* 371M 的文件( 3000 万的数据) 过滤数据耗时 : 27375 毫秒 * 520M 的文件( 4200 万的数据) 过滤数据耗时 : 62000 毫秒
其中把 4200 万的数据用 BitSet 操作耗时约 20-30 秒,写入目标文件约 30 秒。所以 1 分钟可以搞定 4200 万的数据。效率已经得到了极大的提高。
相关文章推荐
- 海量数据处理系列----C++中Bitmap算法的实现
- 海量数据处理系列——C语言下实现bitmap算法
- [算法系列之十八]海量数据处理之BitMap
- (Java)海量数据处理
- Bitmap和2-Bitmap海量数据处理问题
- java海量数据处理(千万级别)(2)-海量数据FTP下载
- 海量数据去重排序--bitmap(位图法)在java中的实现的两种方法
- 运用bitmap解决一道海量数据处理面试题:在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
- java海量数据处理方法
- 使用Java程序一次分段读取所有数据(如海量数据)并计数处理
- 海量数据处理(1)Bitmap, Bloom Filter, Hash(转)
- 运用bitmap解决一道海量数据处理面试题:在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数。
- 海量数据处理系列之(一)Java线程池使用
- 十七道海量数据处理面试题与Bit-map详解---之我对bitmap的理解
- bitmap处理海量数据
- 使用bitmap处理海量数据
- 【转】 海量数据处理系列----C++中Bitmap算法的实现
- 海量数据处理系列----C++中Bitmap算法的实现
- 海量数据处理系列----C++中Bitmap算法的实现
- [算法系列之十八]海量数据处理之BitMap