您的位置:首页 > 编程语言 > Java开发

JDK中Stack的bug

2017-04-01 22:52 176 查看

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 来遍历得到结果了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: