BitSet的size()方法的原因是什么?

时间:2013-06-02 09:43:11

标签: java bitset

size()类上的java.util.BitSet方法是否有用例?

我的意思是 - JavaDoc明确表示它依赖于实现,它以位为单位返回内部long[]存储的大小。根据它的说法,可以得出结论,你将无法设置比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()方法的用例吗?它有用吗?有没有人用它做任何事情?对于某些手动钻头或类似物品来说,它是否很重要?


编辑(经过更多研究后)

我意识到在Java 1.0中引入了BitSet,而我们使用的大多数类的Collections框架都是在Java 1.2中引入的。所以基本上在我看来size()由于遗留原因而被保留,并且没有真正的用途。新的Collection类没有这样的方法,而有些旧的(例如Vector)也没有。

4 个答案:

答案 0 :(得分:4)

  

我意识到BitSet是在Java 1.0中引入的,而我们使用的大多数类的Collections框架是在Java 1.2中引入的。

正确。

  

所以基本上在我看来,由于遗留原因而保留size()并且没有真正的用途。

是的,差不多。

另一个“size”方法是length(),它为您提供设置位的最大索引。从逻辑角度来看,length()size()更有用......但length()仅在Java 1.2中引入。

唯一(假设的)用例,我可以想到size()可能比length()更好的地方是:

  • 您正在尝试为集合中的位迭代建立“fence post”,并且
  • 很可能你会在结束前停止迭代,
  • 你是否超出最后一点设置并不重要。

在这种情况下,size()可能比length()好,因为这是一个更便宜的电话。 (看一下源代码......)但这很微不足道。

(我想,沿着类似行的另一个用例是当您创建新的BitSet并根据现有size()的{​​{1}}预先分配它时。是边缘的。)

但你对兼容性是正确的。很明显,他们不能摆脱BitSet或改变其语义而不会产生兼容性问题。所以他们可能决定不管它。 (实际上,他们甚至没有看到需要弃用它。在API中使用非特别有用的方法的“危害”很小。)

答案 1 :(得分:1)

如果size方法不是由Java创建者设计为公共的,那么它无疑仍然作为私有方法/字段存在。所以我们正在讨论它的可访问性和命名。

Java 1.0从C / C ++中获取了很多灵感,而不仅仅是程序语法。在C ++标准库中,BitSet的{​​{1}}和length的对应项也存在。它们分别称为sizesize。很少有任何硬性理由在C ++中使用capacity,在Java等垃圾收集语言中使用{1}}更少,但是可访问方法仍然有用。我将用Java术语解释。

告诉我,执行capacity操作(例如BitSet)所需的最大机器指令数是多少?人们想回答“只是少数”,但只有当特定操作不会导致整个底层数组的重新分配时才会这样。从理论上讲,重新分配将恒定时间算法转换为线性时间算法。

这种理论差异是否具有很大的实际影响?很少。阵列通常不会经常增长。但是,只要您的算法在逐渐增长的set上运行且具有近似已知的最终大小,如果您已将最终大小传递给BitSet的构造函数,则将节省重新分配。在一些非常特殊的情况下,这甚至可能会产生明显的影响,在大多数情况下它并没有受到伤害。

  • BitSet然后具有恒定的时间复杂度 - 称它不能长时间阻止应用程序。
  • 如果只有一个非常大的set实例耗尽了所有可用内存(按设计),则交换可能会在以后明显地取决于JVM如何实现增长操作(使用或不使用额外的副本)。 / LI>

现在假设您在许多BitSets上运行,所有BitSet都已分配了目标大小。您正在构建另一个BitSet实例,并且您希望新的实例共享旧的目标大小,因为您知道将并排使用它们。公共BitSet方法使得更容易实现干净。

答案 2 :(得分:0)

0和1的数量必须是64的倍数。你可以使用基数()作为1的数量。

答案 3 :(得分:0)

我认为它可能有用的一个主要原因是我们需要扩展BitSet类并覆盖length方法。在这种情况下,大小是有用的。下面是长度如何通过依赖大小方法返回值。

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;
 }