2017-03-29 11 views
1

java.util.concurrent.BlockingQueue 편리한 contains 방법이있다하십시오 predicate/검색 기준을 적용 :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); 

내 필요가 조금 더 구체적이다. 이 작동

Using a ArrayBlockQueue 
    Invoking toArray 

의 짧은 ...하지만 큐가 대형 인 경우에 할 수있는 방법이 있습니까? 이로 인해 메모리 할당 문제가 발생할 수 있습니다.

+0

쉿 행동. – pvg

+0

@pvg 검색은 메시지에서 특정 ID를 찾는 것을 기반으로합니다. 고정 된 술어를 기반으로하는 "여러"대기열이있는 경우는 아닙니다. 이 방법을 사용할 때 모든 메시지에 대한 대기열이 필요합니다. – javadba

+0

메시지 ID가 고유하다면 .equals를 재정의해야합니다. 또는 우선 순위를 설정하십시오. 특정 메시지를 식별해야하는 경우 주문을 부과하는 대기열을 사용할 때 어떤 점이 있습니까? '대기열을 대기열처럼 행동하게 만드는 방법'대신 해결하려는 문제를 설명해야합니다. – 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 do와 같은 많은 차단 대기열 구현이 있습니다.

+0

그것은 무서운!그러나 콜렉션 구현이 equals를 호출 할 수 없으므로 "과소 평가 된"의미로 작동하지 않을 수도 있습니다. "이 사양은 Collection.contains를 null이 아닌 인수로 호출하면 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 
    } 
} 

갖는 다음과 같은 출력이 발견 된 값 대신 이상한, 비 queue-에 큐 구둣 주걱하려고 여러 큐에 대한 좋은 사례처럼 보인다

Element{id=5, message=Default msg} 
Element{id=105, message=Default msg}