閱讀《Java核心技術》的時候,讀到了BitSet這個集合。
有一個例子是Eratosthenes 之篩算法,這個算法的主要做用是查找必定範圍以內的全部質數,對此比較感興趣,因此用Boolean數組和BitSet各作了一遍,又在兩臺電腦上各實現了兩種算法。java
在實現的過程當中,遇到了一些問題,會在最後提出,這裏不說廢話了,先說正事~算法
因爲一個合數老是能夠分解成若干個質數的乘積,那麼若是把質數(最初只知道2是質數)的倍數都去掉,那麼剩下的就是質數了。
例如要查找100之內的質數,首先2是質數,把2的倍數去掉;此時3沒有被去掉,可認爲是質數,因此把3的倍數去掉;再到5,再到7,7以後呢,由於8,9,10剛纔都被去掉了,而100之內的任意合數確定都有一個因子小於10(100的開方),因此,去掉,2,3,5,7的倍數後剩下的都是質數了。數組
public class ArrayTest { public static void main(String[] args) { int sum = 0; final int TOTAL = 2_000_001; Boolean[] array = new Boolean[TOTAL]; long startTime = System.currentTimeMillis(); for(int i = 2;i<TOTAL;i++) { array[i] = true; } for(int i = 2;i<Math.sqrt(TOTAL);i++) { for(int j = i;i*j<TOTAL;j++) { array[i*j] = false; } } long endTime = System.currentTimeMillis(); for(int i = 2;i<TOTAL;i++) { if(true==array[i]) { sum ++; } } System.out.println("There is "+ sum + " prime number"); System.out.println("Total time is "+ (endTime - startTime)); } }
import java.util.BitSet; public class BitSetTest { public static void main(String[] args) { int sum = 0; final int TOTAL = 2_000_001; BitSet aBitSet = new BitSet(TOTAL); long startTime = System.currentTimeMillis(); for(int i = 2;i<TOTAL;i++) { aBitSet.set(i); } for(int i = 2;i<Math.sqrt(TOTAL);i++) { for(int j = i;i*j<TOTAL;j++) { aBitSet.clear(i*j); } } long endTime = System.currentTimeMillis(); for(int i = 2;i<TOTAL;i++) { if(true==aBitSet.get(i)) { sum ++; } } System.out.println("There is "+ sum + " prime number"); System.out.println("Total time is "+ (endTime - startTime)); } }
而後各測試了三次,測試的結果是這樣子的:性能
能夠看到三次平均下來,BitSet的性能仍是稍微好一些的。測試
可是!可是!可是!spa
我在另一臺電腦上用相同的代碼跑出來的結果卻很不同。命令行
另一臺電腦跑出來的結果,利用數組實現(也就是上面的ArrayTest)的速度很是快,常常時間在16-32毫秒之間。而用BitSet實現(也就是上面的BitSetTest)的倒是150-160左右。code
兩臺機器的配置是同樣的,win7,32位,4GB,3.2GHZ。
一開始覺得是編譯器的問題,後來發現不用編譯器用命令行獲得的結果也是有差別的。blog
算法的原理和實現已經懂了一些,可是帶出來了這些問題,有木有大神解釋一下啊。ip