为什么Java Collections.asLifoQueue不是LIFO?

时间:2017-03-12 16:58:15

标签: java collections

请参阅下面的代码:

public class test1 {
    public static void main(String args[]) {
        Deque<String> dq = new ArrayDeque<String>(5);
        dq.add("java");
        dq.add("c");
        dq.add("c++");
        dq.add("unix");
        dq.add("perl");
        Queue<String> q = Collections.asLifoQueue(dq);
        System.out.println("returned queue is: "+q.toString());
    }
}

输出:

returned queue is: [java, c, c++, unix, perl]

输出不应该是以下内容吗?:

[perl, unix, c++, c, java] 

2 个答案:

答案 0 :(得分:1)

Collections.asLifeQueue方法不会影响原始集合中已有的元素。示例代码是对原始集合(具有FIFO语义)和包装集合的混合操作,该集合具有LIFO语义。这就是为什么它没有像你期望的那样工作的原因。

要获得所需的效果,请在创建后立即包装原始集合,然后对包装器执行所有操作:

    Queue<String> q = Collections.asLifoQueue(new ArrayDeque<>());
    q.add("java");
    q.add("c");
    q.add("c++");
    q.add("unix");
    q.add("perl");
    System.out.println("returned queue is: "+q.toString());

这给出了您的预期输出:

returned queue is: [perl, unix, c++, c, java]

答案 1 :(得分:0)

HereasLifoQueue的javadoc。这就是它所说的:

  

返回Deque作为后进先出(Lifo)队列的视图。方法   add映射到push,remove映射到pop等等。这个观点   当您想要使用需要队列的方法时,它可能很有用   但你需要Lifo订购。

因此,它从现有队列中为您提供了LIFO view,这意味着现有队列保持原样,但新方法调用遵循LIFO标准。

现在,在您的示例中,如果我再次调用add,在获得LIFO队列后,它会被转换为push,因此,元素会添加到顶部,例如:

public static void main(String[] args) throws Exception{
     Deque<String> dq = new ArrayDeque<String>(5);
        dq.add("java");
        dq.add("c");
        dq.add("c++");
        dq.add("unix");
        dq.add("perl");
        Queue<String> q = Collections.asLifoQueue(dq);
        q.add("test");
        while(!q.isEmpty()){
            System.out.println(q.remove());
        }
 }

在执行上述操作时首先打印'test'。