9.6.5 BitSet

9.6.5 BitSet

BitSet存储一个bit序列(BitSet并不符合数学上的Set定义,BitVector或BitArray这样的名字会更合适)。在需要存储bit序列(例如flags)时,BitSet底层实现比ArrayList<Boolean>更紧凑,因此也更高效
BitSet可以方便地读取、设置和重置单个bit。而用int或long存储bit序列时需要进行繁琐的masking和位操作。

C++ Note
C++ bitset模板提供与Java BitSet类相同的功能

java.util.BitSet (from Version1.0)

方法描述
BitSet(int initialCapacity)构造方法
int length()返回BitSet的长度
boolean get(int bit)读取一个bit
void set(int bit))Set一个bit
void clear(int bit)Reset一个bit
void and(BitSet set)与set进行逻辑AND
void or(BitSet set)与set进行逻辑OR
void xor(BitSet set)与set进行逻辑XOR
void andNot(BitSet set)与(set的逻辑NOT)进行逻辑AND

我们通过实现“Eratosthenes筛”算法来展示BitSet的用法。(这其实并不是寻找素数的最好方法。但出于某种原因,该算法被普遍用作测试编译器性能的一个benchmark。然而它也不是一个好的benchmark,因为它主要测试位操作。)
我们的程序统计2到2000000之间的素数个数。其思路很简单:遍历一个包含2000001 bit的BitSet,BitSet中第n位bit值就代表数值n的flag(例如,如果第1000位为false,就表示数值1000不是素数)。首先,将所有位置true;然后,如果一个数已知是素数,则该数的倍数就不是素数,将与它们相对应的位都改为false。整个迭代过程完成后,那些仍然为true的位就都是素数了。Listing 9.8是Java程序,Listing 9.9是对应的C++程序。

虽然筛算法算不上一个好的benchmark,我们还是忍不住用它来测试了一下这两种实现。看看在一台具有2.9GHz酷睿双核处理器,8G内存,运行Ubuntu 14.04的ThinkPad上的结果:
C++(g++ 4.6.3): 390ms
Java(Java SE8): 119ms
我们已经在本书的九个版本中运行了测试。在后面五个版本中,Java都轻松击败了C++。但是如果我们调高C++编译器的优化水平,它会比Java快上33ms。只有在程序运行了足够多次,以致引发Hotspot JIT编译后,Java才能也这么快。

//Listing 9.8 Sieve/Sieve.java
import java.util.*;
public class Sieve{
	public static void main(String[] args){
		int n = 2000000;
		BitSet b = new BitSet(n+1);
		int count = 0;
		int i;
		for(i = 2; i<=n; i++)
			b.set(i);
		i = 2;
		while(i*i <= n){
			if(b.get(i)){
				count++;
				int k = 2*i;
				while(k<=n){
					b.clear(k);
					k+=i;
				}
			}
			i++;
		}
		while(i<=n){
			if(b.get(i)) count++;
		}
	}
}
//Listing 9.9 sieve/sieve.cpp
#include<bitset>
#include<iostream>
using namespace std;
int main()
{
	const int N = 2000000;
	bitset<N+1> b;
	int count = 0;
	int i;
	for(i =2; i<=N; i++)
		b.set(i);
	i = 2;
	while(i*i<=N)
	{
		if(b.test(i))
		{
			count++;
			int k = 2*i;
			while(k<=N)
			{
				b.reset(k);
				k+=i;
			}
		}
		i++;
	}
	while(i<=N)
	{
		if(b.test(i))
			count++;
		i++;
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值