微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么Joshua Bloch在有效Java中使用2 * size +1来调整堆栈大小?

如何解决为什么Joshua Bloch在有效Java中使用2 * size +1来调整堆栈大小?

这是我正在谈论的代码

public class Stack {
  private Object[] elements;
  private int size = 0;
  private static final int DEFAULT_INITIAL_CAPACITY = 16;
  public Stack() {
    elements = new Object[DEFAULT_INITIAL_CAPACITY];
  }
  public void push(Object e) {
    ensureCapacity();
    elements[size++] = e;
  }
  public Object pop() {
    if (size == 0)
      throw new EmptyStackException();
    return elements[--size];
  }
  /**
   * Ensure space for at least one more element,roughly
   * doubling the capacity each time the array needs to grow.
   */
  private void ensureCapacity() {
    if (elements.length == size)
      elements = Arrays.copyOf(elements,2 * size + 1);
  }
}

为什么不简单地将最后一行保留为elements = Arrays.copyOf(elements,2 * size);

唯一有效的情况是Stack的初始大小为0。但是在这种情况下,它是一个常量-DEFAULT_INITIAL_CAPACITY(非零值)。而且没有其他重载的构造函数可以从用户那里获取此值(或认为0)

解决方法

我将其解释为对假设的未来错误的安心防御。的确,按照此类编写,此类的数组容量不会为0,因此添加1并不是严格必须的,但是一旦添加了更多功能,这种假设就会悄然失败。

可能的附加功能示例包括java.util.ArrayList中的功能,该功能具有可以将容量设置为0的trimToSize()方法,以及允许初始化(可能为空)集合中的数据的构造函数,以及一个允许将容量显式设置为0的构造函数。您还可以想象一个功能,该功能在清空此类时自动降低其分配的容量。也许有人会编辑DEFAULT_INITIAL_CAPACITY常量。现在想象一下,改变容量的方法被一堆的Javadoc注释分隔开来,并分裂成多个子类。很容易忘记您应该防止容量变为0。

如果ensureCapacity()的大小不为零,则在重做该类时,必须始终牢记这一假设。添加+1是一种低成本的更改,消除了这种麻烦。这也是处理边缘情况的简单算术方法的一个示例。

,

对我来说,似乎比@Boann所用的所有措辞都更明显,尽管他/她的答案的确比他/她的答案更简单。答案很简单,就是作者希望支持以DEFAULT_INITIAL_CAPACITY = 0的零大小启动数组。如果没有+1,这将导致代码崩溃。 elements数组的大小永远不会为零,除非它以这种方式开始,这是+1的唯一原因。

在编写代码时,没有理由使用+1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。