2017-03-29 4 views
1

java.util.concurrent.BlockingQueueが便利contains方法があります。java.util.concurrent.BlockingQueueの述語(/ find/search)が含まれていますか?

/** 
* Returns {@code true} if this queue contains the specified element. 
* More formally, returns {@code true} if and only if this queue contains 
* at least one element {@code e} such that {@code o.equals(e)}. 
* 
* @param o object to be checked for containment in this queue 
* @return {@code true} if this queue contains the specified element 
* @throws ClassCastException if the class of the specified element 
*   is incompatible with this queue 
*   (<a href="../Collection.html#optional-restrictions">optional</a>) 
* @throws NullPointerException if the specified element is null 
*   (<a href="../Collection.html#optional-restrictions">optional</a>) 
*/ 
public boolean contains(Object o); 

を私の必要性は、もう少し具体的です:predicate /検索条件を適用します。この短くする方法はありますか

Using a ArrayBlockQueue 
    Invoking toArray 

これは動作しますが、キューが大きい場合はどうなりますか?これはメモリ割り当ての問題を引き起こす可能性があります。

+0

代わりにいくつかの奇妙な、非queue-にキューを押し込もしようとする複数のキューのために良い場合のように思えます嫌な行動。 – pvg

+0

@pvg検索は、メッセージ内の特定のIDを見つけることに基づいています。固定述部に基づいて「複数の」キューを持つケースはありません。そのアプローチに従えば、すべてのメッセージのキューが必要です。 – javadba

+0

メッセージIDが一意である場合は、.equalsを上書きするだけです。または何らかの優先順位を設定します。特定のメッセージを特定する必要がある場合、注文を課すキューを使用するポイントは何ですか?キューをnot-a-queueのように振る舞うにはどうすればいいのか、解決しようとしている問題を説明する必要があります。 – pvg

答えて

0

私はあなたがこれを実行する必要があるかどうかわかりませんが、あなたそれを行うことができますようにそれはそう:

public static class Matcher<T> { 

    Predicate<T> predicate; 
    Class<T> clazz; 

    public Matcher(Predicate<T> t, Class<T> clazz) { 
     this.predicate = t; 
     this.clazz = clazz; 
    } 

    @SuppressWarnings("unchecked") 
    public boolean equals(Object o) { 
     if (o != null && this.clazz.isInstance(o)) { 
      System.out.println("Checking item " + o + " against predicate " + this.predicate); 
      return this.predicate.test((T) o); 
     } 
     return false; 
    } 
} 

public static void main(String args[]) { 

    ArrayBlockingQueue<Integer> oddsOnly = new ArrayBlockingQueue<>(10); 
    oddsOnly.addAll(Arrays.asList(1, 3, 5, 7, 9, 11, 13)); 

    ArrayBlockingQueue<Integer> oddsAndEves = new ArrayBlockingQueue<>(10); 
    oddsAndEves.addAll(Arrays.asList(1, 2, 3, 4, 5)); 

    Predicate<Integer> evenPredicate = (i) -> i % 2 == 0; 
    System.out.println(oddsOnly.contains(new Matcher<>(evenPredicate, Integer.class))); // prints false 

    System.out.println(oddsAndEves.contains(new Matcher<>(evenPredicate, Integer.class))); // prints true 
} 

出力:

Checking item 1 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 3 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 5 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 7 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 9 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 11 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 13 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
false 
Checking item 1 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
Checking item 2 against predicate QueueEquals$Matcher$$Lambda$1/[email protected] 
true 

をそれは私が望ん作るんしかし、シャワーを浴びる...プラス、pvgが正しく指摘している - これは動作するとは限りません。 BlockingQueueの実装は、equals()を呼び出す前にhashCode()を呼び出すことがあります。

sanerオプションは、ブロッキングキューを反復処理し、各要素に対して述語を実行することです。 BlockingQueueインターフェイスにはiteratorがありませんが、多くのブロックキューの実装(ArrayBlockingQueueLinkedBlockingQueueなど)があります。

+0

それは恐ろしいです!しかし、コレクションの実装がequalsを呼び出すことが保証されていないため、(賢明な意味で)「保証」されていないこともあります。 "この仕様は、null以外の引数を指定してCollection.containsを呼び出すとo.equals(e)が呼び出される原因を意味すると解釈されるべきではありません。e" – pvg

+0

私はその感想を共有します。それは恐ろしいですが、equalsを呼び出す前に 'hashCode'を呼び出さない実装ではうまくいくでしょう。とにかく、私は答えの一番下にsanerのソリューションを追加しました。 – Malt

0

Queue(必要に応じて並行して)をストリームして、述語を使用して要素を除外することができます。 BlockingQueueQueueであり、これはCollectionであり、したがってstream()parallelStream()と定義します。以下に沿って何か:

次の出力見つかった値を持つ
public class SampleApplication { 

    private static final int ELEMENT_COUNT = 100000; 

    public static void main(String[] args) { 
     Queue<Element> blockingQueue = new ArrayBlockingQueue<>(ELEMENT_COUNT); 
     List<Element> elements = Stream.generate(SampleApplication::createElement).limit(ELEMENT_COUNT).collect(Collectors.toList()); 
     blockingQueue.addAll(elements); 

     blockingQueue.stream().filter(getFilterPredicate(5)).findAny().ifPresent(System.out::println); 
     blockingQueue.stream().filter(getFilterPredicate(105)).findAny().ifPresent(System.out::println); 
     blockingQueue.stream().filter(getFilterPredicate(-1)).findAny().ifPresent(System.out::println); 
    } 

    private static Predicate<Element> getFilterPredicate(int value) { 
     return e -> e.getId() == value; 
    } 

    private static int i = 0; 
    private static Element createElement() { 
     return new Element(++i); 
    } 

    static class Element { 
     private int id; 
     private String message; 

     public Element(int id) { 
      this.id = id; 
      this.message = "Default msg"; 
     } 

     //Getters, Setters & toString omitted 
    } 
} 

Element{id=5, message=Default msg} 
Element{id=105, message=Default msg} 
関連する問題