JDK中Stack的bug

来源:互联网 发布:编程用什么软件比较好 编辑:程序博客网 时间:2024/06/05 10:51

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 来遍历得到结果了。

0 0