2013-06-02 22 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; 
}