如何使用循环从Java中删除队列中的元素

Jos*_*osh 8 java loops blockingqueue

我有这样的数据结构:

BlockingQueue mailbox = new LinkedBlockingQueue();

我正在尝试这样做:

for(Mail mail: mailbox)
{
    if(badNews(mail))
    {
        mailbox.remove(mail);
    }
}
Run Code Online (Sandbox Code Playgroud)

显然循环的内容会干扰边界并触发错误,所以我通常会这样做:

for(int i = 0;  i < mailbox.size(); i++)
{
    if(badNews(mailbox.get(i)))
    {
        mailbox.remove(i);
        i--;
    }
}
Run Code Online (Sandbox Code Playgroud)

但遗憾的是BlockingQueue没有按索引获取或删除元素的功能,所以我卡住了.有任何想法吗?

编辑 - 一些澄清:我的目标之一是保持相同的顺序,从头部弹出并将其放回尾部是不好的.此外,虽然没有其他线程会从邮箱中删除邮件,但是它们会添加到邮箱中,因此我不希望处于删除算法的中间,让某人向我发送邮件,然后发生异常.

提前致谢!

Lui*_*oza 3

您可以 p\xcc\xb6o\xcc\xb6p\xcc\xb6 poll和 p\xcc\xb6u\xcc\xb6s\xcc\xb6h\xcc\xb6 offer队列中的所有元素,直到对队列进行完整循环。这是一个例子:

\n\n
Mail firstMail = mailbox.peek();\nMail currentMail = mailbox.pop();\nwhile (true) {\n    //a base condition to stop the loop\n    Mail tempMail = mailbox.peek();\n    if (tempMail == null || tempMail.equals(firstMail)) {\n        mailbox.offer(currentMail);\n        break;\n    }\n    //if there\'s nothing wrong with the current mail, then re add to mailbox\n    if (!badNews(currentMail)) {\n        mailbox.offer(currentMail);\n    }\n    currentMail = mailbox.poll();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

请注意,只有当此代码在单个线程中执行并且没有其他线程从此队列中删除项目时,此方法才有效。

\n\n

也许您需要检查是否确实想要轮询或从 BlockingQueue 中获取元素。报价和看跌期权类似。

\n\n

更多信息:

\n\n\n\n
\n\n

另一种错误较少的方法是使用临时集合(不一定是并发的),并将仍然需要的元素存储在队列中。这是一个启动示例:

\n\n
List<Mail> mailListTemp = new ArrayList<>();\nwhile (mailbox.peek() != null) {\n    Mail mail = mailbox.take();\n    if (!badNews(mail)) {\n        mailListTemp.add(mail);\n    }\n}\nfor (Mail mail : mailListTemp) {\n    mailbox.offer(mail);\n}\n
Run Code Online (Sandbox Code Playgroud)\n