2013-06-02 52 views
14

java.util.BitSet類的size()方法有用例嗎?BitSet的size()方法的原因是什麼?

我的意思是 - JavaDoc清楚地說它是依賴於實現的,它以比特的形式返回內部存儲的大小。從它說什麼,我們可以得出這樣的結論,你將不能夠設置一個位,且比size()更高的指數,但事實並非如此,在BitSet可以自動增長:

BitSet myBitSet = new BitSet(); 
System.out.println(myBitSet.size()); // prints "64" 
myBitSet.set(768); 
System.out.println(myBitSet.size()); // prints "832" 

BitSet每一個相遇我曾在我的生活,我一直想用length()因爲這一個返回BitSet的邏輯大小:

BitSet myBitSet = new BitSet(); 
System.out.println(myBitSet.length()); // prints "0" 
myBitSet.set(768); 
System.out.println(myBitSet.length()); // prints "769" 

即使我已經爲過去6年編寫的Java,這兩種方法都始終高度讓我困惑。我經常把它們混在一起並順便用錯,因爲在我的腦海中,我認爲BitSet是一個聰明的Set<boolean>,我會用size()

就好像ArrayListlength()返回元素的數量,size()返回底層數組的大小。

現在,有沒有用於我缺少的size()方法的任何用例?它以任何方式有用嗎?有沒有人曾經用它來做任何事情?可能對於一些手動翻轉或類似的東西很重要?


編輯(經過一些調查研究)

我意識到BitSet在Java 1.0中引入,而與大多數我們使用的類集合框架中的Java 1.2中引入的。所以基本上,我認爲size()是因爲遺留原因而被保留的,並且沒有真正的用途。新的集合類沒有這樣的方法,而一些舊的(例如Vector)。

回答

4

我意識到BitSet是在Java 1.0中引入的,而我們使用的大多數類的Collections框架都是在Java 1.2中引入的。

正確。

因此,基本上我認爲尺寸()是因爲遺留原因而保留的,並沒有真正的用處。

是的,非常多。

另一個「大小」方法是length()它給你一個位設置的最大索引。從邏輯角度來看,length()size()更有用......但length()僅在Java 1.2中引入。

唯一的(假設的)使用-情況下,我能想到的地方size()可能比length()好時:

  • 你正在試圖建立一個「圍欄」在該位的迭代設置和
  • 它很可能會在結束之前停止迭代,並且
  • 無關緊要的是您超出了設置的最後一位。

在這種情況下,size()可以說比length()好,因爲它是一個更便宜的電話。 (查看源代碼...)但這是相當微不足道的。

(我猜,沿着類似的路線另一個用例是當你創建一個新的BitSet和基於現有BitSetsize()預分配它。同樣,不同的是微不足道的。)

但你正確的兼容性。很顯然,他們既不能擺脫size(),也不能改變它的語義而不會產生兼容性問題。所以他們大概決定放棄它。 (事實上​​,他們甚至沒有看到需要棄用它,在API中使用不太有用的方法的「傷害」是最小的)。

+0

好像我是在正確的軌道上畢竟。如果有人對這種方法有革命性的使用,我會稍微等一下,但我猜滴答是屬於你的。他們並沒有貶低它,這真是一種恥辱。這會爲我節省寶貴的時間,當使用錯誤的。 –

0

0和1的數字必須是64的倍數。你可以使用cardinality()作爲1的數量。

+2

我知道它做什麼。但我想知道爲什麼有人會想要調用這種方法。或者首先將其包含在API中。我是否正確地認爲'BitSet'是一個老一代的util類? (見我的編輯) –

+0

這不是「0和1的數字」。它是[「該BitSet實際使用的表示位值的位數」](http://docs.oracle.com/javase/7/docs/api/java/util/BitSet.html#size ())。 – EJP

+1

@EJP雖然這可能是更清晰,看不出區別。是否有空間不充滿0和1? –

1

如果size方法不是由Java創建者設計的作爲公衆,它仍然無疑是作爲私人方法/領域存在的。所以我們正在討論它的可訪問性和可能的​​命名。

Java 1.0從C/C++中吸取了很多靈感,而不僅僅是程序語法。在C++標準庫中,也存在BitSetlengthsize的對應部分。他們分別被稱爲sizecapacity。在C++中使用capacity幾乎沒有什麼困難的理由,在垃圾收集語言(如Java)中使用capacity幾乎沒有什麼理由,但讓方法可訪問仍然是有用的。我將用Java術語解釋。

告訴我,執行BitSet操作(例如set)所需的機器指令的最大數量是多少?人們想回答「只有少數幾個」,但只有在特定操作不會導致整個底層數組重新分配的情況下才會如此。理論上,重新分配將恆定時間算法轉換爲線性時間算法。

這種理論上的差異是否有很大的實際影響?很少。陣列通常不會增長太多。但是,只要您的算法在逐漸增長的BitSet上運行且具有近似已知的最終大小,如果您已將最終大小傳遞給BitSet的構造函數,則將節省重新分配。在一些非常特殊的情況下,這甚至會有明顯的效果,在大多數情況下它不會受到傷害。

  • set然後有恆定的時間複雜性 - 稱它永遠不能阻止應用程序太久。
  • 如果只有一個非常大的BitSet實例正在使用所有可用內存(按設計),交換可能會明顯啓動,這取決於您的JVM如何實現增長操作(帶或不帶額外的副本)。

現在想象你在許多BitSets上運行,所有這些都已經被分配了一個目標大小。您正在構建從另一個位集合實例,你想,你知道你將要使用它們並排的新共享舊的目標大小。公開size方法可以更輕鬆地實現乾淨。

0

其中一個主要的原因我認爲這可能是有用的是,當我們需要擴展位集合類並覆蓋長度的方法。在這種情況下,大小是有用的。以下是長度返回值與大小方法的依賴關係。

protected Set bitset; 
public int length() { 
    int returnValue = 0; 
    // Make sure set not empty 
    // Get maximum value +1 
    if (bitset.size() > 0) { 
    Integer max = (Integer)Collections.max(bitset); 
    returnValue = max.intValue()+1; 
    } 
    return returnValue; 
}