我有这样的数据结构:
BlockingQueue mailBox = new LinkedBlockingQueue();
我正在尝试这样做:
for(Mail mail: mailBox) { if(badNews(mail)) { mailBox.remove(mail); } }
for(int i = 0; i < mailBox.size(); i++) { if(badNews(mailBox.get(i))) { mailBox.remove(i); i--; } }
但遗憾的是BlockingQueue没有按索引获取或删除元素的功能,所以我卡住了.有任何想法吗?
编辑 – 一些澄清:
我的目标之一是保持相同的顺序,从头部弹出并将其放回尾部是不好的.此外,虽然没有其他线程会从邮箱中删除邮件,但是它们会添加到邮箱中,因此我不希望处于删除算法的中间,让某人向我发送邮件,然后发生异常.
提前致谢!
解决方法
您可以在队列中完成所有元素,直到队列中的所有元素为止,然后才能使用
poll
和p̶u̶s̶h̶
offer
.这是一个例子:
Mail firstMail = mailBox.peek(); Mail currentMail = mailBox.pop(); while (true) { //a base condition to stop the loop Mail tempMail = mailBox.peek(); if (tempMail == null || tempMail.equals(firstMail)) { mailBox.offer(currentMail); break; } //if there's nothing wrong with the current mail,then re add to mailBox if (!badNews(currentMail)) { mailBox.offer(currentMail); } currentMail = mailBox.poll(); }
请注意,只有在单个线程中执行此代码并且没有其他线程从此队列中删除项目时,此方法才有效.
也许您需要检查是否真的要轮询或从BlockingQueue中获取元素.提供和放置类似.
更多信息:
> Java BlockingQueue take() vs poll()
> LinkedBlockingQueue put vs offer
另一种不那么错误的方法是使用临时集合,不一定是并发的,并将您仍需要的元素存储在队列中.这是一个启动示例:
List<Mail> mailListTemp = new ArrayList<>(); while (mailBox.peek() != null) { Mail mail = mailBox.take(); if (!badNews(mail)) { mailListTemp.add(mail); } } for (Mail mail : mailListTemp) { mailBox.offer(mail); }