4

我正在使用 Java 邮件 API 接收来自多个 gmail 帐户的邮件。不同的帐户正在由不同的线程处理,我正在使用 aLinkedBlockingQueue来存储电子邮件。但是,我不希望将相同的电子邮件重复添加到Queue. 这是我到目前为止的代码:

public synchronized void readMail(){
    try {
        boolean alreadyAdded = false;
        Folder inbox = store.getFolder("Inbox");
        inbox.open(Folder.READ_ONLY);
        Message [] received = inbox.getMessages();

        if(messages.isEmpty()){
            for(Message newMessage:received){
                System.out.println("Queue empty, adding messages");
                messages.put(newMessage);
            }
        }

        else{
            for(Message existingMessage:messages){
                for(Message newMessage:received){
                    if (alreadyAdded == true)
                        break;

                    else{
                        if(existingMessage.getSubject().equals(newMessage.getSubject())){
                            alreadyAdded = true;
                            System.out.println("boolean changed to true, message "+newMessage.getSubject()+"won't be added");
                        }

                        else{
                            alreadyAdded = false;
                            System.out.println("Non-duplicate message "+newMessage.getSubject());
                            messages.put(newMessage);
                        }
                    }
                }
            }
        }
    } 
    catch (MessagingException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

我遇到的问题是在检查队列是否为空else之后的块中。if我希望它检查刚刚读入的消息集,并将这些消息与Queue. 如果消息在,Queue请不要再次添加。我不能简单地使用.contains(),因为每次下载消息时,它们都会被赋予不同的内存位置,因此尽管Message对象实际上可能是相同的(例如具有相同的主题、内容等),但它不会具有相同的签名(例如第一次下载它可能是Messagehgshsh676767但下一次可能是Messageyyetwt8965)。

我碰到了一堵砖墙,谁能建议一种方法来确保不添加重复项?

4

2 回答 2

1

您可以为您的消息创建一个包装类,该类将包含一个适当的equals方法,基于例如主题

public class MyMessage {
    final private Message msg;

    public MyMessage (final Message msg) {
        this.msg = msg;
    }

    public boolean equals (final Object other) {
        if (!(other instanceof MyMessage)) {
            return false;
        }

        final MyMessage otherMessage = (MyMessage) other;
        return msg.getSubject ().equals (otherMessage.getSubject ());
    }

    public Message getMessage () {
        return msg;
    }
}

如果你不关心顺序,你可以使用一些线程安全的Set实现

final Set<MyMessage> messages = Collections.synchronizedSet (new HashSet<MyMessage> ());

Message [] received = inbox.getMessages();
for (final Message msg : reveived) {
    messages.add (msg);
}    

这样你就不会重复了。

如果您关心订单,请使用一些SortedSet,例如:

public class MyMessage implements Comparable<MyMessage> {
    ... //the same as above

    public int compareTo (final MyMessage otherMessage) {
        return msg.getReceivedDate ().compareTo (otherMessage.getReceivedDate ());
    }
}


final Set<MyMessage> messages = Collections.synchronizedSet (new TreeSet<MyMessage> ());
于 2012-11-13T17:18:26.290 回答
-1
if(!queue.contains(element)) {
    queue.add(element);
}

如果你想要一个 Set,你可以扩展 LinkedBlockingQueue 并覆盖 add:

public boolean add(E e)
    if(!this.contains(e)) {
        return super.add(e);
    } else {
        return false;
    }
}

但是您应该要么制作它并在本地使用它,要么正确地覆盖它——所有可以向它添加元素的方法和构造函数。

关于包含问题,在收到的消息上创建一个包装器并正确实施该public boolean equals(Object o)方法。当您收到消息时,将其放入此包装器并将此包装器放入集合中。

于 2012-11-13T17:10:13.063 回答