JDK中Stack的bug

JDK中Stack的bug

在写 Dijkstra 的最短路径算法的时候,打印结果发现和预期的结果不同,查找出来的路径刚好是反着的。在经过多次bug排查后最后发现问题在路径的打印上面。

Stack<DirectedEdge> path = new Stack<>();
for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()])
      path.push(e);

由于此处我使用了 Stack 去储存路径(得到路径的顺序本身是反着的),我以为直接 foreach 打印结果当然是从上到下的。可是并不是这样。通过下面代码我们就可以看出来:

public static void main(String[] args) {
    Stack<Integer> tmp = new Stack<>();
    tmp.push(1);
    tmp.push(2);
    tmp.push(3);
    for (Integer e : tmp)
        System.out.println(e);
}

是的,结果并不是3 2 1,而是1 2 3,这是为什么呢?

原因

是的,这是 JDK 的一个bug。在官方文档中,找到了回答:Java bugs官方文档,正如文中所说:It was an incorrect design decision to have Stack extend Vector (“is-a” rather than “has-a”). We sympathize with the submitter but cannot fix this becauseof compatibility.

大意就是,是由于 Stack 继承自 Vector 类,所以用的是 Vector 的 iterator,这是他们设计的问题,但是由于兼容性问题,所以他们没办法解决。

解决办法

最后我使用了 LinkedList 来代替 Stack 使用,在源码中我们可以看到向 LinkedList 中插入元素有两中方法:

/**
* Appends the specified element to the end of this list.
*
* <p>This method is equivalent to {@link #addLast}.
*
* @param e element to be appended to this list
* @return {@code true} (as specified by {@link Collection#add})
*/
public boolean add(E e) {
  linkLast(e);
  return true;
}


/**
* Pushes an element onto the stack represented by this list.  In other
* words, inserts the element at the front of this list.
*
* <p>This method is equivalent to {@link #addFirst}.
*
* @param e the element to push
* @since 1.6
*/
public void push(E e) {
    addFirst(e);
}

也就是 add() 和 push()的区别,具体介绍源码已经写得很清楚了,头插和尾插的不同。这样一来,我们就可以安心的使用 foreach 来遍历得到结果了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值