Skip to content

Commit

Permalink
Implement method to add all collection elements to a PriorityQueue
Browse files Browse the repository at this point in the history
  • Loading branch information
BaurzhanSakhariev committed Mar 27, 2022
1 parent ff263f0 commit 47a2c13
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ protected boolean lessThan(SubIterator a, SubIterator b) {

boolean hasImpacts = false;
List<Impact> onlyImpactList = null;
List<SubIterator> subIterators = new ArrayList<>();
for (int i = 0; i < impacts.length; ++i) {
int impactsLevel = getLevel(impacts[i], docIdUpTo);
if (impactsLevel == -1) {
Expand All @@ -284,7 +285,7 @@ protected boolean lessThan(SubIterator a, SubIterator b) {
}

SubIterator subIterator = new SubIterator(impactList);
pq.add(subIterator);
subIterators.add(subIterator);
if (hasImpacts == false) {
hasImpacts = true;
onlyImpactList = impactList;
Expand All @@ -308,6 +309,7 @@ protected boolean lessThan(SubIterator a, SubIterator b) {
// We walk impacts in parallel through a PQ ordered by freq. At any time,
// the competitive impact consists of the lowest freq among all entries of
// the PQ (the top) and the highest norm (tracked separately).
pq.addAll(subIterators);
List<Impact> mergedImpacts = new ArrayList<>();
SubIterator top = pq.top();
int currentFreq = top.current.freq;
Expand Down
27 changes: 27 additions & 0 deletions lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/
package org.apache.lucene.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.Supplier;
Expand Down Expand Up @@ -107,6 +108,32 @@ public PriorityQueue(int maxSize, Supplier<T> sentinelObjectSupplier) {
}
}

/**
* Adds all elements of the collection into the queue. This method should be preferred over
* calling add() in loop if all elements are known in advance as it builds queue faster.
*/
public void addAll(Collection<T> elements) {
if (this.size + elements.size() > this.maxSize) {
throw new IllegalArgumentException(
"Cannot add "
+ elements.size()
+ " elements to a queue with remaining capacity: "
+ (maxSize - size));
}
// Heap with size S always takes first S elements of the array,
// and thus it's safe to fill array further - no actual non-sentinel value will be overwritten.
Iterator<T> iterator = elements.iterator();
while (iterator.hasNext()) {
this.heap[size + 1] = iterator.next();
this.size++;
}

// The loop goes down to 1 as heap is 1-based not 0-based.
for (int i = (size >>> 1); i >= 1; i--) {
downHeap(i);
}
}

/**
* Determines the ordering of objects in this priority queue. Subclasses must define this one
* method.
Expand Down
37 changes: 37 additions & 0 deletions lucene/core/src/test/org/apache/lucene/util/TestPriorityQueue.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,43 @@ public void testInsertWithOverflow() {
assertEquals((Integer) 2, pq.top());
}

public void testAddAllToEmptyQueue() {
int size = 10;
List<Integer> list = new ArrayList<>();
for (int i = 0; i < size; i++) {
list.add(random().nextInt());
}
IntegerQueue pq = new IntegerQueue(size);
pq.addAll(list);
pq.checkValidity();
}

public void testAddAllToPartiallyFilledQueue() {
IntegerQueue pq = new IntegerQueue(20);
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(random().nextInt());
pq.add(random().nextInt());
}
pq.addAll(list);
pq.checkValidity();
}

public void testAddAllDontFitIntoQueue() {
IntegerQueue pq = new IntegerQueue(20);
List<Integer> list = new ArrayList<>();

for (int i = 0; i < 11; i++) {
list.add(random().nextInt());
pq.add(random().nextInt());
}

assertThrows(
"Cannot add 11 elements to a queue with remaining capacity: 9",
IllegalArgumentException.class,
() -> pq.addAll(list));
}

public void testRemovalsAndInsertions() {
Random random = random();
int numDocsInPQ = TestUtil.nextInt(random, 1, 100);
Expand Down

0 comments on commit 47a2c13

Please sign in to comment.