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

2022-09-03 07:52:47

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

我的意思是 - 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"

在我生命中与我的每一次相遇中,我一直想使用long(),因为那一个返回了逻辑大小的:BitSetBitSet

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

尽管我在过去的6年里一直在编写Java,但这两种方法对我来说总是非常混乱。我经常将它们混合在一起,并偶然使用错误的一个,因为在我的脑海中,我认为我会使用.BitSetSet<boolean>size()

这就像如果返回元素的数量并返回基础数组的大小一样。ArrayListlength()size()

现在,我缺少的方法是否有任何用例?它有什么用处吗?有没有人用过它?对于一些手动摆动或类似的东西来说,这可能很重要吗?size()


编辑(经过更多的研究)

我意识到是在Java 1.0中引入的,而我们使用的大多数类的集合框架是在Java 1.2中引入的。所以基本上在我看来,这是由于遗产原因而保留的,它没有真正的用途。新的 Collection 类没有这样的方法,而一些旧类(例如 Vector)有。BitSetsize()


答案 1

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

正确。

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

是的,差不多。

另一种“大小”方法是为您提供设置位的最大索引。从逻辑的角度来看,比...但只是在Java 1.2中引入的。length()length()size()length()

我能想到的唯一(假设的)用例可能比以下情况更好:size()length()

  • 您正在尝试为集合中位的迭代建立一个“栅栏柱”,并且
  • 您很可能会在结束之前停止迭代,并且
  • 重要的是你超越了设置的最后一点。

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

(我猜,另一个类似的用例是,当您创建一个新的并根据现有 .同样,差异很小。BitSetsize()BitSet

但是,关于兼容性,你是对的。很明显,他们无法在不产生兼容性问题的情况下摆脱或更改其语义。所以他们大概决定不去管它。(事实上,他们甚至没有看到需要弃用它。在API中使用不是特别有用的方法的“危害”是最小的。size()


答案 2

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

Java 1.0 从 C/C++ 中汲取了很多灵感,而不仅仅是过程语法。在C++标准库中,与 的对应项也存在。它们分别被称为 那里 和 。在C++中很少有任何困难的理由使用,在诸如Java之类的垃圾回收语言中更是如此,但是具有可访问的方法仍然可以说是有用的。我将用Java术语进行解释。BitSetlengthsizesizecapacitycapacity

告诉我,执行诸如此类的操作所需的最大机器指令数是多少?有人想回答“只是少数几个”,但只有当该特定操作不会导致整个底层阵列的重新分配时,这才是正确的。从理论上讲,重新分配将恒定时间算法转换为线性时间算法。BitSetset

这种理论上的差异是否具有很大的实际影响?很少。数组通常不会增长太频繁。但是,每当有一个算法在逐渐增长的算法上以大约已知的最终大小运行时,如果将最终大小已经传递给 的构造函数,则可以节省重新分配。在某些非常特殊的情况下,这甚至可能产生明显的效果,在大多数情况下,它不会造成伤害。BitSetBitSet

  • set然后具有恒定的时间复杂性 - 调用它不能阻止应用程序太长时间。
  • 如果只有一个非常大的实例占用了所有可用内存(根据设计),则交换可能会在以后明显开始,具体取决于 JVM 如何实现增长操作(有或没有额外的副本)。BitSet

现在假设您在许多 BitSet 上运行,所有这些 BitSet 都已分配有目标大小。您正在从另一个 BitSet 实例构造一个实例,并且您希望新的实例共享旧实例的目标大小,因为您知道您将并排使用它们。公开该方法可以使其更易于干净利落地实现。size


推荐