4

Java メール API を使用して、複数の Gmail アカウントからメッセージを受信して​​います。さまざまなアカウントがさまざまなスレッドで処理されておりLinkedBlockingQueue、メールを保存するために を使用しています。ただし、同じメールが繰り返し に追加されるのは望ましくありません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);
}

セットが必要な場合は、LinkedBlockingQueueを拡張して、addをオーバーライドできます。

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

ただし、それを作成してローカルで使用するか、適切にオーバーライドする必要があります。要素を追加できるすべてのメソッドとコンストラクターです。

containsの問題については、受信したメッセージのラッパーを作成し、public boolean equals(Object o)メソッドを適切に実装してください。メッセージを受け取ったら、それをこのラッパーに入れ、このラッパーをコレクションに入れます。

于 2012-11-13T17:10:13.063 に答える