16

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,但这两种方法对我来说总是非常混乱。我经常把它们混在一起,顺便用错了,因为在我的脑海里,我认为BitSetSet<boolean>会在哪里使用size().

这就像如果ArrayList返回length()元素的数量并size()返回底层数组的大小。

size()现在,我缺少的方法有什么用例吗?它在任何方面都有用吗?有没有人用过它?对于一些手动操作或类似的东西可能很重要吗?


编辑(经过更多研究)

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

4

4 回答 4

6

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

正确的。

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

是的,差不多。

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

我能想到的唯一(假设的)用例size()可能比length()何时更好:

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

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

(我想,另一个类似的用例是当您创建一个新的BitSet并根据size()现有的. 预分配它时BitSet。同样,差异是微不足道的。)

但是您对兼容性是正确的。很明显,他们不能摆脱size()或改变其语义而不产生兼容性问题。所以他们大概决定不理会它。(事实上​​,他们甚至没有看到有必要弃用它。在 API 中使用不是特别有用的方法的“危害”是最小的。)

于 2013-06-02T10:13:14.963 回答
1

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

Java 1.0 从 C/C++ 中汲取了很多灵感,而不仅仅是过程语法。BitSet在 C++ 标准库中, 'length和的对应物size也存在。它们分别被称为sizecapacity。在 C++中使用很少有任何硬性理由,capacity在 Java 这样的垃圾收集语言中更是如此,但让方法可访问仍然可以说是有用的。我将用 Java 术语进行解释。

BitSet告诉我,执行诸如 之类的操作所需的最大机器指令数是set多少?有人想回答“只是少数”,但这仅在该特定操作不会导致整个底层数组的重新分配时才成立。从理论上讲,重新分配将恒定时间算法转变为线性时间算法。

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

  • setthen 具有恒定的时间复杂度 - 调用它永远不会阻塞应用程序太久。
  • 如果只有一个非常大BitSet的实例耗尽了所有可用内存(按设计),则交换可能会在稍后明显开始,具体取决于您的 JVM 如何实现增长操作(有或没有额外副本)。

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

于 2013-06-02T11:25:18.110 回答
0

它是 0 和 1 的数量,必须是 64 的倍数。您可以使用 cardinality() 作为 1 的数量。

于 2013-06-02T09:47:17.557 回答
0

我认为它可能有用的主要原因之一是当我们需要扩展 BitSet 类并覆盖 length 方法时。在这种情况下,大小很有用。下面是 length 如何根据 size 方法返回值。

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;
 }
于 2015-04-28T06:25:49.323 回答