如何增大java.util.Stack实例的默认容量?
问题分析与解决方案
首先得澄清一个关键误解:你遇到的StackOverflowError大概率不是Stack容器的容量不够导致的,而是递归调用过深触发了Java虚拟机的调用栈溢出——这是两个完全不同的概念。
先回答你关于Stack容量的问题:
Stack继承自Vector,而Vector本身是会自动扩容的:默认初始容量是10,当元素数量超过当前容量时,它会自动把容量扩容为原来的2倍(你也可以通过ensureCapacity(int minCapacity)方法提前指定最小容量)。比如你可以在初始化destinations的时候调用:
这个方法会确保Stack的底层容量至少达到20,不会像this.destinations.ensureCapacity(20);setSize()那样添加null元素,只是提前完成扩容操作,避免后续自动扩容的性能开销。- 另外,
Vector永远不会因为容量不足抛出StackOverflowError,最多只会在内存耗尽时抛出OutOfMemoryError,所以你遇到的错误肯定不是容器容量的问题。
你的代码问题:递归调用导致的调用栈溢出
看你的代码逻辑,每次传送失败时,你会把当前目标加入栈,然后递归调用sendTransporterToHuman处理新的目标;传送成功后,又会递归弹出栈里的目标处理。这种递归方式如果遇到连续多次失败的情况,递归深度会不断累积,一旦超过JVM的默认调用栈深度(通常在几百到几千之间,取决于JVM参数),就会抛出StackOverflowError。
解决这个问题的最佳方式是把递归改成迭代,用循环来处理栈里的目标,避免调用栈被耗尽:
private void sendTransporterToHuman(Coord initialDest) { Coord currentDest = initialDest; while (true) { boolean successfulJourney = sendTransporterTo(currentDest, HUMAN); if (successfulJourney) { if (this.destinations.isEmpty()) { break; } else { currentDest = this.destinations.pop(); } } else { this.destinations.add(currentDest); currentDest = new Coord(currentDest.X() - 1, currentDest.Y()); } } }
这个迭代版本的逻辑和你原来的递归逻辑完全一致,但不会产生递归调用栈的累积,也就不会触发StackOverflowError。
额外提示
如果你确实想确认Stack的容量情况,可以调用capacity()方法(继承自Vector)查看当前的底层容量,size()方法查看实际元素数量,两者是不同的概念:
size():当前Stack中的元素个数capacity():底层数组的总容量(可以容纳的元素数,不扩容的情况下)
内容的提问来源于stack exchange,提问作者Gaurav Agarwal
相关产品推荐
相关产品推荐

