|
23 | 23 | import java.util.ArrayList;
|
24 | 24 | import java.util.Collections;
|
25 | 25 | import java.util.Deque;
|
| 26 | +import java.util.HashSet; |
26 | 27 | import java.util.List;
|
27 | 28 | import java.util.Set;
|
28 | 29 | import java.util.concurrent.ConcurrentHashMap;
|
@@ -63,6 +64,27 @@ public Cache<String, List<QueryIndex<V>>> get() {
|
63 | 64 | }
|
64 | 65 | }
|
65 | 66 |
|
| 67 | + /** |
| 68 | + * Dedup values as they are consumed. This is used to avoid processing the same result |
| 69 | + * multiple times in the case of OR clauses where multiple match the same data point. |
| 70 | + */ |
| 71 | + private static class DedupConsumer<T> implements Consumer<T> { |
| 72 | + |
| 73 | + private final Consumer<T> consumer; |
| 74 | + private final Set<T> alreadySeen; |
| 75 | + |
| 76 | + DedupConsumer(Consumer<T> consumer) { |
| 77 | + this.consumer = consumer; |
| 78 | + this.alreadySeen = new HashSet<>(); |
| 79 | + } |
| 80 | + |
| 81 | + @Override public void accept(T t) { |
| 82 | + if (alreadySeen.add(t)) { |
| 83 | + consumer.accept(t); |
| 84 | + } |
| 85 | + } |
| 86 | + } |
| 87 | + |
66 | 88 | /**
|
67 | 89 | * Return a new instance of an index that is empty. The default caching behavior will be
|
68 | 90 | * used.
|
@@ -365,7 +387,7 @@ public List<T> findMatches(Id id) {
|
365 | 387 | * Function to invoke for values associated with a query that matches the id.
|
366 | 388 | */
|
367 | 389 | public void forEachMatch(Id id, Consumer<T> consumer) {
|
368 |
| - forEachMatch(id, 0, consumer); |
| 390 | + forEachMatch(id, 0, new DedupConsumer<>(consumer)); |
369 | 391 | }
|
370 | 392 |
|
371 | 393 | @SuppressWarnings("PMD.NPathComplexity")
|
@@ -473,6 +495,10 @@ public List<T> findMatches(Function<String, String> tags) {
|
473 | 495 | * Function to invoke for values associated with a query that matches the id.
|
474 | 496 | */
|
475 | 497 | public void forEachMatch(Function<String, String> tags, Consumer<T> consumer) {
|
| 498 | + forEachMatchImpl(tags, new DedupConsumer<>(consumer)); |
| 499 | + } |
| 500 | + |
| 501 | + private void forEachMatchImpl(Function<String, String> tags, Consumer<T> consumer) { |
476 | 502 | // Matches for this level
|
477 | 503 | matches.forEach(consumer);
|
478 | 504 |
|
|
0 commit comments