我正在迭代它时更新ConcurrentLinkedQueue
。从理论上讲,此队列上的迭代器不应该停止,直到达到队列结束。但是,在我的程序中(如下所示),迭代器在迭代队列的初始状态(没有更新)之后停止。我该怎么做才能克服这个问题?
public static void printTree(Node root) {
Queue<Node>q=new ConcurrentLinkedQueue<Node>();
q.add(root);
Iterator<Node> iter = q.iterator();
while(iter.hasNext()) {
List<Node> childs = iter.next().getChildren();
for(Node child:childs) {
q.add(child);
}
}
for (Node item:q) {
System.out.println(item.getValue());
}
}
它的输出是root的值(传递给函数的值)及其子值。它应该显示孩子的孩子的价值,但不是。似乎迭代器iter
只迭代root
,它首先被添加到队列而不是更多。
答案 0 :(得分:1)
在ConcurrentLinkedQueue#iterator()的javadoc中:
返回的迭代器(...)保证遍历元素 在构造迭代器时存在,并且可能(但不是 保证)反映施工后的任何修改。
基本上,当您创建迭代器时,它将在队列创建视图时提供视图。这是此Collection是线程安全的原因之一:更改队列将并行完成,即不影响现有迭代器。
在这种情况下无需使用线程安全集合。您可以使用支持ListIterator
的List。 ListIterator
是一个功能更强大的iterator
,它支持添加元素:
List<Node>q=new LinkedList<Node>();
q.add(root);
ListIterator<Node> iter = q.iterator();
while(iter.hasNext()) {
List<Node> childs = iter.next().getChildren();
for(Node child:childs) {
iter.add(child);
}
}
for (Node item:q) {
System.out.println(item.getValue());
}
这是该方法的替代实现,不使用迭代器,我更喜欢:
List<String> q = new LinkedList<>();
q.add(root);
while(!q.isEmpty()) {
Node node = q.poll();
q.addAll(node.getChildren());
System.out.println(node.getValue());
}