Skip to content

Commit 39b0a7e

Browse files
committed
fix(#15309): Optimize PriorityQueue.remove() function
1 parent 71e822e commit 39b0a7e

File tree

1 file changed

+48
-36
lines changed

1 file changed

+48
-36
lines changed

lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java

Lines changed: 48 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
import java.util.Arrays;
2020
import java.util.Collection;
2121
import java.util.Comparator;
22+
import java.util.HashMap;
2223
import java.util.Iterator;
24+
import java.util.Map;
2325
import java.util.NoSuchElementException;
2426
import java.util.function.IntFunction;
2527
import java.util.function.Supplier;
@@ -72,6 +74,7 @@ public static <T> PriorityQueue<T> usingComparator(
7274
private final int maxSize;
7375
private final T[] heap;
7476
private final LessThan<? super T> lessThan;
77+
private final Map<T, Integer> indexMap = new HashMap<>();
7578

7679
/** Create an empty priority queue of the configured size using the specified {@link LessThan}. */
7780
public PriorityQueue(int maxSize, LessThan<? super T> lessThan) {
@@ -272,6 +275,7 @@ public final int size() {
272275
public final void clear() {
273276
Arrays.fill(heap, 0, size + 1, null);
274277
size = 0;
278+
indexMap.clear();
275279
}
276280

277281
/**
@@ -280,20 +284,21 @@ public final void clear() {
280284
* constant remove time but the trade-off would be extra cost to all additions/insertions)
281285
*/
282286
public final boolean remove(T element) {
283-
for (int i = 1; i <= size; i++) {
284-
if (heap[i] == element) {
285-
heap[i] = heap[size];
286-
heap[size] = null; // permit GC of objects
287-
size--;
288-
if (i <= size) {
289-
if (!upHeap(i)) {
290-
downHeap(i);
291-
}
292-
}
293-
return true;
287+
Integer idx = indexMap.get(element);
288+
if (idx == null || idx > size || heap[idx] != element) return false;
289+
heap[idx] = heap[size];
290+
indexMap.remove(element);
291+
if (idx != size) {
292+
indexMap.put(heap[idx], idx);
293+
}
294+
heap[size] = null;
295+
size--;
296+
if (idx <= size) {
297+
if (!upHeap(idx)) {
298+
downHeap(idx);
294299
}
295300
}
296-
return false;
301+
return true;
297302
}
298303

299304
/**
@@ -320,36 +325,43 @@ public T[] drainToArrayHighestFirst(IntFunction<T[]> newArray) {
320325
return array;
321326
}
322327

323-
private boolean upHeap(int origPos) {
324-
int i = origPos;
325-
T node = heap[i]; // save bottom node
326-
int j = i >>> 1;
327-
while (j > 0 && lessThan.lessThan(node, heap[j])) {
328-
heap[i] = heap[j]; // shift parents down
329-
i = j;
330-
j = j >>> 1;
331-
}
332-
heap[i] = node; // install saved node
333-
return i != origPos;
328+
protected final void addToHeap(int idx, T element) {
329+
heap[idx] = element;
330+
indexMap.put(element, idx);
334331
}
335332

336-
private void downHeap(int i) {
337-
T node = heap[i]; // save top node
338-
int j = i << 1; // find smaller child
339-
int k = j + 1;
340-
if (k <= size && lessThan.lessThan(heap[k], heap[j])) {
341-
j = k;
333+
protected boolean upHeap(int i) {
334+
T node = heap[i];
335+
int j = i;
336+
while (j > 1 && lessThan.lessThan(node, heap[j >> 1])) {
337+
heap[j] = heap[j >> 1];
338+
indexMap.put(heap[j], j);
339+
j >>= 1;
342340
}
343-
while (j <= size && lessThan.lessThan(heap[j], node)) {
344-
heap[i] = heap[j]; // shift up child
345-
i = j;
346-
j = i << 1;
347-
k = j + 1;
348-
if (k <= size && lessThan.lessThan(heap[k], heap[j])) {
341+
heap[j] = node;
342+
indexMap.put(node, j);
343+
return j < i;
344+
}
345+
346+
protected boolean downHeap(int i) {
347+
T node = heap[i];
348+
int j = i;
349+
int k;
350+
while ((k = j << 1) <= size) {
351+
if (k < size && lessThan.lessThan(heap[k + 1], heap[k])) {
352+
k++;
353+
}
354+
if (lessThan.lessThan(heap[k], node)) {
355+
heap[j] = heap[k];
356+
indexMap.put(heap[j], j);
349357
j = k;
358+
} else {
359+
break;
350360
}
351361
}
352-
heap[i] = node; // install saved node
362+
heap[j] = node;
363+
indexMap.put(node, j);
364+
return j > i;
353365
}
354366

355367
/**

0 commit comments

Comments
 (0)