diff --git a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene60/bkd/BKDWriter60.java b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene60/bkd/BKDWriter60.java index 14da2cbd62e0..46738f11b439 100644 --- a/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene60/bkd/BKDWriter60.java +++ b/lucene/backward-codecs/src/test/org/apache/lucene/backward_codecs/lucene60/bkd/BKDWriter60.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.function.IntFunction; import org.apache.lucene.codecs.CodecUtil; @@ -453,29 +454,14 @@ public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) { } } - private static class BKDMergeQueue extends PriorityQueue { - private final int bytesPerDim; - - public BKDMergeQueue(int bytesPerDim, int maxSize) { - super(maxSize); - this.bytesPerDim = bytesPerDim; - } - - @Override - public boolean lessThan(MergeReader a, MergeReader b) { - assert a != b; - - int cmp = - Arrays.compareUnsigned(a.packedValue, 0, bytesPerDim, b.packedValue, 0, bytesPerDim); - if (cmp < 0) { - return true; - } else if (cmp > 0) { - return false; - } - - // Tie break by sorting smaller docIDs earlier: - return a.docID < b.docID; - } + private static Comparator mergeComparator(int bytesPerDim) { + return ((Comparator) + (a, b) -> { + assert a != b; + return Arrays.compareUnsigned( + a.packedValue, 0, bytesPerDim, b.packedValue, 0, bytesPerDim); + }) + .thenComparingInt(mr -> mr.docID); } /** @@ -642,7 +628,8 @@ public long merge(IndexOutput out, List docMaps, List queue = + PriorityQueue.usingComparator(readers.size(), mergeComparator(config.bytesPerDim())); for (int i = 0; i < readers.size(); i++) { PointValues pointValues = readers.get(i); diff --git a/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java b/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java index 8c0fb5433d02..6ef14ff03e38 100644 --- a/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java +++ b/lucene/classification/src/java/org/apache/lucene/classification/utils/NearestFuzzyQuery.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Objects; @@ -40,6 +41,7 @@ import org.apache.lucene.search.QueryVisitor; import org.apache.lucene.search.TermQuery; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.FloatComparator; import org.apache.lucene.util.PriorityQueue; import org.apache.lucene.util.automaton.LevenshteinAutomata; @@ -125,7 +127,8 @@ public void addTerms(String queryString, String fieldName) { fieldVals.add(new FieldVals(fieldName, maxEdits, queryString)); } - private void addTerms(IndexReader reader, FieldVals f, ScoreTermQueue q) throws IOException { + private void addTerms(IndexReader reader, FieldVals f, PriorityQueue q) + throws IOException { if (f.queryString == null) return; final Terms terms = MultiTerms.getTerms(reader, f.fieldName); if (terms == null) { @@ -141,8 +144,8 @@ private void addTerms(IndexReader reader, FieldVals f, ScoreTermQueue q) throws String term = termAtt.toString(); if (!processedTerms.contains(term)) { processedTerms.add(term); - ScoreTermQueue variantsQ = - new ScoreTermQueue( + PriorityQueue variantsQ = + createScoreTermQueue( MAX_VARIANTS_PER_TERM); // maxNum variants considered for any one term float minScore = 0; Term startTerm = new Term(f.fieldName, term); @@ -214,7 +217,7 @@ private Query newTermQuery(IndexReader reader, Term term) throws IOException { @Override public Query rewrite(IndexSearcher indexSearcher) throws IOException { IndexReader reader = indexSearcher.getIndexReader(); - ScoreTermQueue q = new ScoreTermQueue(MAX_NUM_TERMS); + PriorityQueue q = createScoreTermQueue(MAX_NUM_TERMS); // load up the list of possible terms for (FieldVals f : fieldVals) { addTerms(reader, f, q); @@ -275,19 +278,11 @@ private static class ScoreTerm { } } - private static class ScoreTermQueue extends PriorityQueue { - ScoreTermQueue(int size) { - super(size); - } - - /* (non-Javadoc) - * @see org.apache.lucene.util.PriorityQueue#lessThan(java.lang.Object, java.lang.Object) - */ - @Override - protected boolean lessThan(ScoreTerm termA, ScoreTerm termB) { - if (termA.score == termB.score) return termA.term.compareTo(termB.term) > 0; - else return termA.score < termB.score; - } + private static PriorityQueue createScoreTermQueue(int size) { + return PriorityQueue.usingComparator( + size, + FloatComparator.comparing(st -> st.score) + .thenComparing(st -> st.term, Comparator.reverseOrder())); } @Override diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/sharedterms/STUniformSplitTermsWriter.java b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/sharedterms/STUniformSplitTermsWriter.java index 7e469bcb774a..badf681048c3 100755 --- a/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/sharedterms/STUniformSplitTermsWriter.java +++ b/lucene/codecs/src/java/org/apache/lucene/codecs/uniformsplit/sharedterms/STUniformSplitTermsWriter.java @@ -164,13 +164,14 @@ private Collection writeSingleSegment( throws IOException { List fieldMetadataList = createFieldMetadataList(new FieldsIterator(fields, fieldInfos), maxDoc); - TermIteratorQueue fieldTermsQueue = + PriorityQueue> fieldTermsQueue = createFieldTermsQueue(fields, fieldMetadataList); List> groupedFieldTerms = new ArrayList<>(fieldTermsQueue.size()); List termStates = new ArrayList<>(fieldTermsQueue.size()); while (fieldTermsQueue.size() != 0) { - TermIterator topFieldTerms = fieldTermsQueue.popTerms(); + TermIterator topFieldTerms = fieldTermsQueue.pop(); + assert topFieldTerms != null && topFieldTerms.term != null; BytesRef term = BytesRef.deepCopyOf(topFieldTerms.term); groupByTerm(fieldTermsQueue, topFieldTerms, groupedFieldTerms); writePostingLines(term, groupedFieldTerms, normsProducer, termStates); @@ -190,9 +191,10 @@ private List createFieldMetadataList(Iterator fieldInf return fieldMetadataList; } - private TermIteratorQueue createFieldTermsQueue( + private PriorityQueue> createFieldTermsQueue( Fields fields, List fieldMetadataList) throws IOException { - TermIteratorQueue fieldQueue = new TermIteratorQueue<>(fieldMetadataList.size()); + PriorityQueue> fieldQueue = + PriorityQueue.usingComparator(fieldMetadataList.size(), Comparator.naturalOrder()); for (FieldMetadata fieldMetadata : fieldMetadataList) { Terms terms = fields.terms(fieldMetadata.getFieldInfo().name); if (terms != null) { @@ -207,7 +209,7 @@ private TermIteratorQueue createFieldTermsQueue( } private void groupByTerm( - TermIteratorQueue termIteratorQueue, + PriorityQueue> termIteratorQueue, TermIterator topTermIterator, List> groupedTermIterators) { groupedTermIterators.clear(); @@ -243,7 +245,8 @@ private void writePostingLines( } private void nextTermForIterators( - List> termIterators, TermIteratorQueue termIteratorQueue) + List> termIterators, + PriorityQueue> termIteratorQueue) throws IOException { for (TermIterator termIterator : termIterators) { if (termIterator.nextTerm()) { @@ -330,7 +333,8 @@ private Collection mergeSegments( mergeState.mergeFieldInfos.iterator(), mergeState.segmentInfo.maxDoc()); Map fieldTermsMap = createMergingFieldTermsMap(fieldMetadataList, mergeState.fieldsProducers.length); - TermIteratorQueue segmentTermsQueue = createSegmentTermsQueue(segmentTermsList); + PriorityQueue> segmentTermsQueue = + createSegmentTermsQueue(segmentTermsList); List> groupedSegmentTerms = new ArrayList<>(segmentTermsList.size()); Map> fieldPostingsMap = CollectionUtil.newHashMap(mergeState.fieldInfos.length); @@ -338,7 +342,8 @@ private Collection mergeSegments( List termStates = new ArrayList<>(mergeState.fieldInfos.length); while (segmentTermsQueue.size() != 0) { - TermIterator topSegmentTerms = segmentTermsQueue.popTerms(); + TermIterator topSegmentTerms = segmentTermsQueue.pop(); + assert topSegmentTerms != null && topSegmentTerms.term != null; BytesRef term = BytesRef.deepCopyOf(topSegmentTerms.term); groupByTerm(segmentTermsQueue, topSegmentTerms, groupedSegmentTerms); combineSegmentsFields(groupedSegmentTerms, fieldPostingsMap); @@ -364,9 +369,10 @@ private Map createMergingFieldTermsMap( return fieldTermsMap; } - private TermIteratorQueue createSegmentTermsQueue( + private PriorityQueue> createSegmentTermsQueue( List> segmentTermsList) throws IOException { - TermIteratorQueue segmentQueue = new TermIteratorQueue<>(segmentTermsList.size()); + PriorityQueue> segmentQueue = + PriorityQueue.usingComparator(segmentTermsList.size(), Comparator.naturalOrder()); for (TermIterator segmentTerms : segmentTermsList) { if (segmentTerms.nextTerm()) { // There is at least one term in the segment @@ -447,26 +453,7 @@ PostingsEnum getPostings(String fieldName, PostingsEnum reuse, int flags) throws } } - private class TermIteratorQueue extends PriorityQueue> { - - TermIteratorQueue(int numFields) { - super(numFields); - } - - @Override - protected boolean lessThan(TermIterator a, TermIterator b) { - return a.compareTo(b) < 0; - } - - TermIterator popTerms() { - TermIterator topTerms = pop(); - assert topTerms != null; - assert topTerms.term != null; - return topTerms; - } - } - - private abstract class TermIterator implements Comparable> { + private abstract static class TermIterator implements Comparable> { BytesRef term; @@ -485,7 +472,7 @@ public int compareTo(TermIterator other) { abstract int compareSecondary(TermIterator other); } - private class FieldTerms extends TermIterator { + private static class FieldTerms extends TermIterator { final FieldMetadata fieldMetadata; final TermsEnum termsEnum; @@ -520,7 +507,7 @@ void resetIterator(BytesRef term, List segmentPostingsList) { } } - private class SegmentTerms extends TermIterator { + private static class SegmentTerms extends TermIterator { private final Integer segmentIndex; private final STMergingBlockReader mergingBlockReader; diff --git a/lucene/core/src/java/org/apache/lucene/index/DocIDMerger.java b/lucene/core/src/java/org/apache/lucene/index/DocIDMerger.java index dd1840ca850a..bf01fcdd497c 100644 --- a/lucene/core/src/java/org/apache/lucene/index/DocIDMerger.java +++ b/lucene/core/src/java/org/apache/lucene/index/DocIDMerger.java @@ -145,13 +145,12 @@ private SortedDocIDMerger(List subs, int maxCount) throws IOException { } this.subs = subs; queue = - new PriorityQueue(maxCount - 1) { - @Override - protected boolean lessThan(Sub a, Sub b) { - assert a.mappedDocID != b.mappedDocID; - return a.mappedDocID < b.mappedDocID; - } - }; + PriorityQueue.usingComparator( + maxCount - 1, + (a, b) -> { + assert a.mappedDocID != b.mappedDocID; + return Integer.compare(a.mappedDocID, b.mappedDocID); + }); reset(); } diff --git a/lucene/core/src/java/org/apache/lucene/index/DocValuesFieldUpdates.java b/lucene/core/src/java/org/apache/lucene/index/DocValuesFieldUpdates.java index ffcb9f07c9b1..5fe0d20b25da 100644 --- a/lucene/core/src/java/org/apache/lucene/index/DocValuesFieldUpdates.java +++ b/lucene/core/src/java/org/apache/lucene/index/DocValuesFieldUpdates.java @@ -18,6 +18,7 @@ import static org.apache.lucene.search.DocIdSetIterator.NO_MORE_DOCS; +import java.util.Comparator; import org.apache.lucene.search.DocIdSetIterator; import org.apache.lucene.util.Accountable; import org.apache.lucene.util.BytesRef; @@ -159,24 +160,12 @@ public static Iterator mergedIterator(Iterator[] subs) { return subs[0]; } + // sort by smaller docID, then larger delGen PriorityQueue queue = - new PriorityQueue(subs.length) { - @Override - protected boolean lessThan(Iterator a, Iterator b) { - // sort by smaller docID - int cmp = Integer.compare(a.docID(), b.docID()); - if (cmp == 0) { - // then by larger delGen - cmp = Long.compare(b.delGen(), a.delGen()); - - // delGens are unique across our subs: - assert cmp != 0; - } - - return cmp < 0; - } - }; - + PriorityQueue.usingComparator( + subs.length, + Comparator.comparingInt(Iterator::docID) + .thenComparing(Comparator.comparingLong(Iterator::delGen).reversed())); for (Iterator sub : subs) { if (sub.nextDoc() != NO_MORE_DOCS) { queue.add(sub); diff --git a/lucene/core/src/java/org/apache/lucene/index/MultiSorter.java b/lucene/core/src/java/org/apache/lucene/index/MultiSorter.java index 5c3c25be55e5..422a9072a7df 100644 --- a/lucene/core/src/java/org/apache/lucene/index/MultiSorter.java +++ b/lucene/core/src/java/org/apache/lucene/index/MultiSorter.java @@ -18,6 +18,7 @@ package org.apache.lucene.index; import java.io.IOException; +import java.util.Comparator; import java.util.List; import org.apache.lucene.index.MergeState.DocMap; import org.apache.lucene.search.Sort; @@ -82,24 +83,22 @@ static MergeState.DocMap[] sort(Sort sort, List readers) throws IOE int leafCount = readers.size(); PriorityQueue queue = - new PriorityQueue(leafCount) { - @Override - public boolean lessThan(LeafAndDocID a, LeafAndDocID b) { - for (int i = 0; i < comparables.length; i++) { - int cmp = Long.compare(a.valuesAsComparableLongs[i], b.valuesAsComparableLongs[i]); - if (cmp != 0) { - return reverseMuls[i] * cmp < 0; - } - } - - // tie-break by docID natural order: - if (a.readerIndex != b.readerIndex) { - return a.readerIndex < b.readerIndex; - } else { - return a.docID < b.docID; - } - } - }; + PriorityQueue.usingComparator( + leafCount, + ((Comparator) + (a, b) -> { + for (int i = 0; i < comparables.length; i++) { + int cmp = + Long.compare( + a.valuesAsComparableLongs[i], b.valuesAsComparableLongs[i]); + if (cmp != 0) { + return reverseMuls[i] * cmp; + } + } + return 0; + }) + .thenComparingInt(ld -> ld.readerIndex) + .thenComparingInt(ld -> ld.docID)); PackedLongValues.Builder[] builders = new PackedLongValues.Builder[leafCount]; diff --git a/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java b/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java index 69237ec4e97d..80371e019e62 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DisjunctionScorer.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import org.apache.lucene.util.FloatComparator; import org.apache.lucene.util.PriorityQueue; /** Base class for Scorers that score disjunctions. */ @@ -88,12 +89,7 @@ private TwoPhase(DocIdSetIterator approximation, float matchCost) { super(approximation); this.matchCost = matchCost; unverifiedMatches = - new PriorityQueue(numClauses) { - @Override - protected boolean lessThan(DisiWrapper a, DisiWrapper b) { - return a.matchCost < b.matchCost; - } - }; + PriorityQueue.usingComparator(numClauses, FloatComparator.comparing(d -> d.matchCost)); } DisiWrapper getSubMatches() throws IOException { diff --git a/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseMatcher.java b/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseMatcher.java index d24b4e9ae654..85f4c212bd1a 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseMatcher.java +++ b/lucene/core/src/java/org/apache/lucene/search/SloppyPhraseMatcher.java @@ -32,6 +32,7 @@ import org.apache.lucene.internal.hppc.IntHashSet; import org.apache.lucene.search.similarities.Similarity.SimScorer; import org.apache.lucene.util.FixedBitSet; +import org.apache.lucene.util.PriorityQueue; /** * Find all slop-valid position-combinations (matches) encountered while traversing/hopping the @@ -56,7 +57,7 @@ public final class SloppyPhraseMatcher extends PhraseMatcher { private final int slop; private final int numPostings; - private final PhraseQueue pq; // for advancing min position + private final PriorityQueue pq; // for advancing min position private final boolean captureLeadMatch; private final DocIdSetIterator approximation; @@ -92,7 +93,22 @@ public SloppyPhraseMatcher( this.slop = slop; this.numPostings = postings.length; this.captureLeadMatch = captureLeadMatch; - pq = new PhraseQueue(postings.length); + pq = + PriorityQueue.usingLessThan( + postings.length, + (pp1, pp2) -> { + if (pp1.position == pp2.position) + // same doc and pp.position, so decide by actual term positions. + // rely on: pp.position == tp.position - offset. + if (pp1.offset == pp2.offset) { + return pp1.ord < pp2.ord; + } else { + return pp1.offset < pp2.offset; + } + else { + return pp1.position < pp2.position; + } + }); phrasePositions = new PhrasePositions[postings.length]; for (int i = 0; i < postings.length; ++i) { phrasePositions[i] = diff --git a/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java b/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java index 8c97983e83aa..b4c2ad27a7f7 100644 --- a/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java +++ b/lucene/core/src/java/org/apache/lucene/search/SynonymQuery.java @@ -511,18 +511,11 @@ public List getImpacts(int level) { } PriorityQueue pq = - new PriorityQueue<>(impacts.length) { - @Override - protected boolean lessThan(SubIterator a, SubIterator b) { - if (a.current == null) { // means iteration is finished - return false; - } - if (b.current == null) { - return true; - } - return Long.compareUnsigned(a.current.norm, b.current.norm) < 0; - } - }; + PriorityQueue.usingComparator( + impacts.length, + Comparator.comparing( + it -> it.current, + Comparator.nullsLast((a, b) -> Long.compareUnsigned(a.norm, b.norm)))); for (List impacts : toMerge) { pq.add(new SubIterator(impacts.iterator())); } diff --git a/lucene/core/src/java/org/apache/lucene/search/PhraseQueue.java b/lucene/core/src/java/org/apache/lucene/util/FloatComparator.java similarity index 55% rename from lucene/core/src/java/org/apache/lucene/search/PhraseQueue.java rename to lucene/core/src/java/org/apache/lucene/util/FloatComparator.java index 5d05292e0e68..c16dda127cc9 100644 --- a/lucene/core/src/java/org/apache/lucene/search/PhraseQueue.java +++ b/lucene/core/src/java/org/apache/lucene/util/FloatComparator.java @@ -14,27 +14,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.lucene.search; +package org.apache.lucene.util; -import org.apache.lucene.util.PriorityQueue; +import java.util.Comparator; -final class PhraseQueue extends PriorityQueue { - PhraseQueue(int size) { - super(size); +/** A specialization of {@link Comparator} that compares {@code float} values */ +@FunctionalInterface +public interface FloatComparator { + + /** Represents a function that returns a {@code float} result */ + @FunctionalInterface + interface ToFloatFunction { + float applyAsFloat(T obj); } - @Override - protected final boolean lessThan(PhrasePositions pp1, PhrasePositions pp2) { - if (pp1.position == pp2.position) - // same doc and pp.position, so decide by actual term positions. - // rely on: pp.position == tp.position - offset. - if (pp1.offset == pp2.offset) { - return pp1.ord < pp2.ord; - } else { - return pp1.offset < pp2.offset; - } - else { - return pp1.position < pp2.position; - } + static Comparator comparing(ToFloatFunction function) { + return (a, b) -> Float.compare(function.applyAsFloat(a), function.applyAsFloat(b)); } + + /** + * Float-specialized {@link Comparator#compare} + * + * @see java.util.Comparator#compare + */ + int compare(float f1, float f2); } diff --git a/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java b/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java index 2ad13d24e3e7..ae995afd076c 100644 --- a/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java +++ b/lucene/core/src/java/org/apache/lucene/util/MergedIterator.java @@ -16,6 +16,7 @@ */ package org.apache.lucene.util; +import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; @@ -44,7 +45,7 @@ */ public final class MergedIterator> implements Iterator { private T current; - private final TermMergeQueue queue; + private final PriorityQueue> queue; private final SubIterator[] top; private final boolean removeDuplicates; private int numTop; @@ -57,7 +58,11 @@ public MergedIterator(Iterator... iterators) { @SuppressWarnings({"unchecked", "rawtypes"}) public MergedIterator(boolean removeDuplicates, Iterator... iterators) { this.removeDuplicates = removeDuplicates; - queue = new TermMergeQueue<>(iterators.length); + queue = + PriorityQueue.usingComparator( + iterators.length, + Comparator., T>comparing(it -> it.current) + .thenComparingInt(it -> it.index)); top = new SubIterator[iterators.length]; int index = 0; for (Iterator iterator : iterators) { @@ -138,21 +143,4 @@ private static class SubIterator> { I current; int index; } - - private static class TermMergeQueue> - extends PriorityQueue> { - TermMergeQueue(int size) { - super(size); - } - - @Override - protected boolean lessThan(SubIterator a, SubIterator b) { - final int cmp = a.current.compareTo(b.current); - if (cmp != 0) { - return cmp < 0; - } else { - return a.index < b.index; - } - } - } } diff --git a/lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java b/lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java index 7900b0f5bc7b..62f747b52492 100644 --- a/lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java +++ b/lucene/core/src/java/org/apache/lucene/util/PriorityQueue.java @@ -37,6 +37,34 @@ */ public abstract class PriorityQueue implements Iterable { + /** Represents a {@code <} operation, which is less prescriptive than {@link Comparator} */ + @FunctionalInterface + public interface LessThan { + boolean lessThan(T a, T b); + } + + /** Create a {@code PriorityQueue} that orders elements using the specified {@code lessThan} */ + public static PriorityQueue usingLessThan(int maxSize, LessThan lessThan) { + return new PriorityQueue<>(maxSize) { + @Override + protected boolean lessThan(T a, T b) { + return lessThan.lessThan(a, b); + } + }; + } + + /** Create a {@code PriorityQueue} that orders elements using the specified {@code lessThan} */ + public static PriorityQueue usingLessThan( + int maxSize, Supplier sentinelObjectSupplier, LessThan lessThan) { + return new PriorityQueue<>(maxSize, sentinelObjectSupplier) { + @Override + protected boolean lessThan(T a, T b) { + return lessThan.lessThan(a, b); + } + }; + } + + /** Create a {@code PriorityQueue} that orders elements using the specified {@code comparator} */ public static PriorityQueue usingComparator( int maxSize, Comparator comparator) { return new PriorityQueue<>(maxSize) { @@ -47,6 +75,17 @@ protected boolean lessThan(T a, T b) { }; } + /** Create a {@code PriorityQueue} that orders elements using the specified {@code comparator} */ + public static PriorityQueue usingComparator( + int maxSize, Supplier sentinelObjectSupplier, Comparator comparator) { + return new PriorityQueue<>(maxSize, sentinelObjectSupplier) { + @Override + protected boolean lessThan(T a, T b) { + return comparator.compare(a, b) < 0; + } + }; + } + private int size = 0; private final int maxSize; private final T[] heap; diff --git a/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java b/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java index 22b3ca90225c..4fbd2a776931 100644 --- a/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java +++ b/lucene/core/src/java/org/apache/lucene/util/bkd/BKDWriter.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Comparator; import java.util.List; import java.util.function.IntFunction; import org.apache.lucene.codecs.CodecUtil; @@ -396,29 +397,14 @@ public Relation compare(byte[] minPackedValue, byte[] maxPackedValue) { } } - private static class BKDMergeQueue extends PriorityQueue { - private final ArrayUtil.ByteArrayComparator comparator; - - public BKDMergeQueue(int bytesPerDim, int maxSize) { - super(maxSize); - this.comparator = ArrayUtil.getUnsignedComparator(bytesPerDim); - } - - @Override - public boolean lessThan(MergeReader a, MergeReader b) { - assert a != b; - - int cmp = comparator.compare(a.packedValue, 0, b.packedValue, 0); - - if (cmp < 0) { - return true; - } else if (cmp > 0) { - return false; - } - - // Tie break by sorting smaller docIDs earlier: - return a.docID < b.docID; - } + private static Comparator mergeComparator(int bytesPerDim) { + ByteArrayComparator comparator = ArrayUtil.getUnsignedComparator(bytesPerDim); + return ((Comparator) + (a, b) -> { + assert a != b; + return comparator.compare(a.packedValue, 0, b.packedValue, 0); + }) + .thenComparingInt(mr -> mr.docID); // Tie break by sorting smaller docIDs earlier } /** flat representation of a kd-tree */ @@ -651,7 +637,8 @@ public IORunnable merge( throws IOException { assert docMaps == null || readers.size() == docMaps.size(); - BKDMergeQueue queue = new BKDMergeQueue(config.bytesPerDim(), readers.size()); + PriorityQueue queue = + PriorityQueue.usingComparator(readers.size(), mergeComparator(config.bytesPerDim())); for (int i = 0; i < readers.size(); i++) { PointValues pointValues = readers.get(i); diff --git a/lucene/facet/src/java/org/apache/lucene/facet/LongValueFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/LongValueFacetCounts.java index 346c2dc369e0..5c4deb32a808 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/LongValueFacetCounts.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/LongValueFacetCounts.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import org.apache.lucene.facet.FacetsCollector.MatchingDocs; import org.apache.lucene.index.DocValues; @@ -419,14 +420,12 @@ public FacetResult getTopChildren(int topN, String dim, String... path) { return new FacetResult(field, new String[0], totCount, new LabelAndValue[0], 0); } + // sort by count descending, breaking ties by value ascending: PriorityQueue pq = - new PriorityQueue<>(Math.min(topN, counts.length + hashCounts.size())) { - @Override - protected boolean lessThan(Entry a, Entry b) { - // sort by count descending, breaking ties by value ascending: - return a.count < b.count || (a.count == b.count && a.value > b.value); - } - }; + PriorityQueue.usingComparator( + Math.min(topN, counts.length + hashCounts.size()), + Comparator.comparingInt(e -> e.count) + .thenComparing(Comparator.comparingLong(dv -> dv.value).reversed())); int childCount = 0; Entry e = null; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/facetset/MatchingFacetSetsCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/facetset/MatchingFacetSetsCounts.java index b17730e7e42d..54501d28e8ec 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/facetset/MatchingFacetSetsCounts.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/facetset/MatchingFacetSetsCounts.java @@ -161,12 +161,8 @@ public FacetResult getTopChildren(int topN, String dim, String... path) throws I topN = Math.min(topN, counts.length); PriorityQueue pq = - new PriorityQueue<>(topN, () -> new Entry("", 0)) { - @Override - protected boolean lessThan(Entry a, Entry b) { - return compare(a.count, b.count, a.label, b.label) < 0; - } - }; + PriorityQueue.usingComparator( + topN, () -> new Entry("", 0), (a, b) -> compare(a.count, b.count, a.label, b.label)); int childCount = 0; Entry reuse = pq.top(); diff --git a/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetCounts.java index 8ab9a5f36485..6bf2f2e2450b 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetCounts.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/range/RangeFacetCounts.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.Collections; +import java.util.Comparator; import java.util.List; import org.apache.lucene.facet.FacetCountsWithFilterQuery; import org.apache.lucene.facet.FacetResult; @@ -223,16 +224,10 @@ public FacetResult getTopChildren(int topN, String dim, String... path) throws I } PriorityQueue pq = - new PriorityQueue<>(Math.min(topN, counts.length)) { - @Override - protected boolean lessThan(Entry a, Entry b) { - int cmp = Integer.compare(a.count, b.count); - if (cmp == 0) { - cmp = b.label.compareTo(a.label); - } - return cmp < 0; - } - }; + PriorityQueue.usingComparator( + Math.min(topN, counts.length), + Comparator.comparingInt(e -> e.count) + .thenComparing(e -> e.label, Comparator.reverseOrder())); int childCount = 0; Entry e = null; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/rangeonrange/RangeOnRangeFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/rangeonrange/RangeOnRangeFacetCounts.java index 7aee5bfdda2d..cd047bee33f7 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/rangeonrange/RangeOnRangeFacetCounts.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/rangeonrange/RangeOnRangeFacetCounts.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.Collections; +import java.util.Comparator; import java.util.List; import org.apache.lucene.document.BinaryRangeDocValues; import org.apache.lucene.document.RangeFieldQuery; @@ -144,16 +145,10 @@ public FacetResult getTopChildren(int topN, String dim, String... path) throws I validateDimAndPathForGetChildren(dim, path); PriorityQueue pq = - new PriorityQueue<>(Math.min(topN, counts.length)) { - @Override - protected boolean lessThan(Entry a, Entry b) { - int cmp = Integer.compare(a.count, b.count); - if (cmp == 0) { - cmp = b.label.compareTo(a.label); - } - return cmp < 0; - } - }; + PriorityQueue.usingComparator( + Math.min(topN, counts.length), + Comparator.comparingInt(e -> e.count) + .thenComparing(e -> e.label, Comparator.reverseOrder())); int childCount = 0; Entry e = null; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java b/lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java index 45464180f57f..f9991008baa6 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/sortedset/AbstractSortedSetDocValueFacetCounts.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -150,18 +151,10 @@ public List getTopDims(int topNDims, int topNChildren) throws IOExc // Creates priority queue to store top dimensions and sort by their aggregated values/hits and // string values. PriorityQueue pq = - new PriorityQueue<>(topNDims) { - @Override - protected boolean lessThan(DimValue a, DimValue b) { - if (a.value > b.value) { - return false; - } else if (a.value < b.value) { - return true; - } else { - return a.dim.compareTo(b.dim) > 0; - } - } - }; + PriorityQueue.usingComparator( + topNDims, + Comparator.comparingInt(dv -> dv.value) + .thenComparing(dv -> dv.dim, Comparator.reverseOrder())); // Keep track of intermediate results, if we compute them, so we can reuse them later: Map intermediateResults = null; diff --git a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacets.java b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacets.java index a9e6cc924d43..172ee8ef00a3 100644 --- a/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacets.java +++ b/lucene/facet/src/java/org/apache/lucene/facet/taxonomy/TaxonomyFacets.java @@ -608,19 +608,10 @@ public List getTopDims(int topNDims, int topNChildren) throws IOExc // Create priority queue to store top dimensions and sort by their aggregated values/hits and // string values. PriorityQueue pq = - new PriorityQueue<>(topNDims) { - @Override - protected boolean lessThan(DimValue a, DimValue b) { - int comparison = valueComparator.compare(a.value, b.value); - if (comparison < 0) { - return true; - } - if (comparison > 0) { - return false; - } - return a.dim.compareTo(b.dim) > 0; - } - }; + PriorityQueue.usingComparator( + topNDims, + Comparator.comparing(dv -> dv.value, valueComparator) + .thenComparing(dv -> dv.dim, Comparator.reverseOrder())); // Keep track of intermediate results, if we compute them, so we can reuse them later: Map intermediateResults = null; diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/Highlighter.java b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/Highlighter.java index cc5587ad50a5..1a17b3267db3 100644 --- a/lucene/highlighter/src/java/org/apache/lucene/search/highlight/Highlighter.java +++ b/lucene/highlighter/src/java/org/apache/lucene/search/highlight/Highlighter.java @@ -18,12 +18,14 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Comparator; import java.util.Iterator; import java.util.Objects; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.OffsetAttribute; +import org.apache.lucene.util.FloatComparator; import org.apache.lucene.util.PriorityQueue; /** @@ -177,7 +179,11 @@ public final TextFragment[] getBestTextFragments( fragmentScorer.startFragment(currentFrag); docFrags.add(currentFrag); - FragmentQueue fragQueue = new FragmentQueue(maxNumFragments); + PriorityQueue fragQueue = + PriorityQueue.usingComparator( + maxNumFragments, + FloatComparator.comparing(TextFragment::getScore) + .thenComparing(Comparator.comparingInt(TextFragment::getFragNum).reversed())); try { @@ -453,16 +459,4 @@ private static void ensureArgumentNotNull(Object argument, String message) { throw new IllegalArgumentException(message); } } - - static class FragmentQueue extends PriorityQueue { - FragmentQueue(int size) { - super(size); - } - - @Override - public final boolean lessThan(TextFragment fragA, TextFragment fragB) { - if (fragA.getScore() == fragB.getScore()) return fragA.fragNum > fragB.fragNum; - else return fragA.getScore() < fragB.getScore(); - } - } } diff --git a/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/PhraseHelper.java b/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/PhraseHelper.java index 8693bcc82f35..ea1622b26b36 100644 --- a/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/PhraseHelper.java +++ b/lucene/highlighter/src/java/org/apache/lucene/search/uhighlight/PhraseHelper.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.Arrays; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -231,12 +232,8 @@ public void createOffsetsEnumsForSpans( // for each SpanQuery, grab it's Spans and put it into a PriorityQueue PriorityQueue spansPriorityQueue = - new PriorityQueue(spanQueries.size()) { - @Override - protected boolean lessThan(Spans a, Spans b) { - return a.startPosition() <= b.startPosition(); - } - }; + PriorityQueue.usingComparator( + spanQueries.size(), Comparator.comparingInt(Spans::startPosition)); for (Query query : spanQueries) { Weight weight = searcher.createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1); diff --git a/lucene/misc/src/java/org/apache/lucene/misc/search/DiversifiedTopDocsCollector.java b/lucene/misc/src/java/org/apache/lucene/misc/search/DiversifiedTopDocsCollector.java index 1aaa6937051b..ef64378af652 100644 --- a/lucene/misc/src/java/org/apache/lucene/misc/search/DiversifiedTopDocsCollector.java +++ b/lucene/misc/src/java/org/apache/lucene/misc/search/DiversifiedTopDocsCollector.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.ArrayDeque; +import java.util.Comparator; import java.util.Deque; import org.apache.lucene.index.LeafReaderContext; import org.apache.lucene.index.NumericDocValues; @@ -30,6 +31,7 @@ import org.apache.lucene.search.TopDocs; import org.apache.lucene.search.TopDocsCollector; import org.apache.lucene.search.TotalHits; +import org.apache.lucene.util.FloatComparator; import org.apache.lucene.util.PriorityQueue; /** @@ -65,18 +67,18 @@ * @lucene.experimental */ public abstract class DiversifiedTopDocsCollector extends TopDocsCollector { + ScoreDocKey spare; - private ScoreDocKeyQueue globalQueue; - private int numHits; - private LongObjectHashMap perKeyQueues; + private final PriorityQueue globalQueue; + private final int numHits; + private final LongObjectHashMap> perKeyQueues; protected int maxNumPerKey; - private Deque sparePerKeyQueues = new ArrayDeque<>(); + private final Deque> sparePerKeyQueues = new ArrayDeque<>(); public DiversifiedTopDocsCollector(int numHits, int maxHitsPerKey) { - super(new ScoreDocKeyQueue(numHits)); - // Need to access pq.lessThan() which is protected so have to cast here... - this.globalQueue = (ScoreDocKeyQueue) pq; - perKeyQueues = new LongObjectHashMap<>(); + super(createScoreDocQueue(numHits)); + this.globalQueue = pq; + this.perKeyQueues = new LongObjectHashMap<>(); this.numHits = numHits; this.maxNumPerKey = maxHitsPerKey; } @@ -100,7 +102,7 @@ protected TopDocs newTopDocs(ScoreDoc[] results, int start) { protected ScoreDocKey insert(ScoreDocKey addition, int docBase, NumericDocValues keys) throws IOException { - if ((globalQueue.size() >= numHits) && (globalQueue.lessThan(addition, globalQueue.top()))) { + if (globalQueue.size() >= numHits && KEY_COMPARATOR.compare(addition, globalQueue.top()) < 0) { // Queue is full and proposed addition is not a globally // competitive score return addition; @@ -121,11 +123,11 @@ protected ScoreDocKey insert(ScoreDocKey addition, int docBase, NumericDocValues // For this to work the choice of key class needs to implement // hashcode and equals. - ScoreDocKeyQueue thisKeyQ = perKeyQueues.get(addition.key); + PriorityQueue thisKeyQ = perKeyQueues.get(addition.key); if (thisKeyQ == null) { - if (sparePerKeyQueues.size() == 0) { - thisKeyQ = new ScoreDocKeyQueue(maxNumPerKey); + if (sparePerKeyQueues.isEmpty()) { + thisKeyQ = createScoreDocQueue(maxNumPerKey); } else { thisKeyQ = sparePerKeyQueues.pop(); } @@ -159,7 +161,7 @@ private void perKeyGroupRemove(ScoreDocKey globalOverflow) { if (globalOverflow == null) { return; } - ScoreDocKeyQueue q = perKeyQueues.get(globalOverflow.key); + PriorityQueue q = perKeyQueues.get(globalOverflow.key); ScoreDocKey perKeyLowest = q.pop(); // The least globally-competitive item should also always be the least // key-local item @@ -205,20 +207,12 @@ public void collect(int doc) throws IOException { }; } - static class ScoreDocKeyQueue extends PriorityQueue { - - ScoreDocKeyQueue(int size) { - super(size); - } + private static final Comparator KEY_COMPARATOR = + FloatComparator.comparing(sd -> sd.score) + .thenComparing(Comparator.comparingInt(sd -> sd.doc).reversed()); - @Override - protected final boolean lessThan(ScoreDocKey hitA, ScoreDocKey hitB) { - if (hitA.score == hitB.score) { - return hitA.doc > hitB.doc; - } else { - return hitA.score < hitB.score; - } - } + private static PriorityQueue createScoreDocQueue(int size) { + return PriorityQueue.usingComparator(size, KEY_COMPARATOR); } // diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/DisjunctionIntervalsSource.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/DisjunctionIntervalsSource.java index 63d66822cabb..b5f7fb35c877 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/DisjunctionIntervalsSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/DisjunctionIntervalsSource.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -168,12 +169,10 @@ static class DisjunctionIntervalIterator extends IntervalIterator { this.approximation = new DisjunctionDISIApproximation(disiQueue); this.iterators = iterators; this.intervalQueue = - new PriorityQueue<>(iterators.size()) { - @Override - protected boolean lessThan(IntervalIterator a, IntervalIterator b) { - return a.end() < b.end() || (a.end() == b.end() && a.start() >= b.start()); - } - }; + PriorityQueue.usingComparator( + iterators.size(), + Comparator.comparingInt(IntervalIterator::end) + .thenComparing(Comparator.comparingInt(IntervalIterator::start).reversed())); float costsum = 0; for (IntervalIterator it : iterators) { costsum += it.cost(); diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java index ea3181ef389e..58da4587056f 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/MinimumShouldMatchIntervalsSource.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -183,19 +184,15 @@ static class MinimumShouldMatchIntervalIterator extends IntervalIterator { this.onMatch = onMatch; this.proximityQueue = - new PriorityQueue(minShouldMatch) { - @Override - protected boolean lessThan(IntervalIterator a, IntervalIterator b) { - return a.start() < b.start() || (a.start() == b.start() && a.end() >= b.end()); - } - }; + PriorityQueue.usingComparator( + minShouldMatch, + Comparator.comparingInt(IntervalIterator::start) + .thenComparing(Comparator.comparingInt(IntervalIterator::end).reversed())); this.backgroundQueue = - new PriorityQueue(subs.size()) { - @Override - protected boolean lessThan(IntervalIterator a, IntervalIterator b) { - return a.end() < b.end() || (a.end() == b.end() && a.start() >= b.start()); - } - }; + PriorityQueue.usingComparator( + subs.size(), + Comparator.comparingInt(IntervalIterator::end) + .thenComparing(Comparator.comparingInt(IntervalIterator::start).reversed())); } @Override diff --git a/lucene/queries/src/java/org/apache/lucene/queries/intervals/UnorderedIntervalsSource.java b/lucene/queries/src/java/org/apache/lucene/queries/intervals/UnorderedIntervalsSource.java index e168905ae992..4df20e4d4987 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/intervals/UnorderedIntervalsSource.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/intervals/UnorderedIntervalsSource.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; +import java.util.Comparator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -108,12 +109,10 @@ private static class UnorderedIntervalIterator extends ConjunctionIntervalIterat UnorderedIntervalIterator(List subIterators, MatchCallback onMatch) { super(subIterators); this.queue = - new PriorityQueue(subIterators.size()) { - @Override - protected boolean lessThan(IntervalIterator a, IntervalIterator b) { - return a.start() < b.start() || (a.start() == b.start() && a.end() >= b.end()); - } - }; + PriorityQueue.usingComparator( + subIterators.size(), + Comparator.comparingInt(IntervalIterator::start) + .thenComparing(Comparator.comparingInt(IntervalIterator::end).reversed())); this.subIterators = new IntervalIterator[subIterators.size()]; this.onMatch = onMatch; diff --git a/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java b/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java index 1683fb681b9c..92ae36434c4b 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/mlt/MoreLikeThis.java @@ -47,6 +47,7 @@ import org.apache.lucene.search.similarities.TFIDFSimilarity; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.CharsRefBuilder; +import org.apache.lucene.util.FloatComparator; import org.apache.lucene.util.PriorityQueue; /** @@ -626,7 +627,8 @@ private PriorityQueue createQueue( Map> perFieldTermFrequencies) throws IOException { // have collected all words in doc and their freqs final int limit = Math.min(maxQueryTerms, this.getTermsCount(perFieldTermFrequencies)); - FreqQ queue = new FreqQ(limit); // will order words by score + PriorityQueue queue = + PriorityQueue.usingComparator(limit, FloatComparator.comparing(st -> st.score)); for (Map.Entry> entry : perFieldTermFrequencies.entrySet()) { Map perWordTermFrequencies = entry.getValue(); String fieldName = entry.getKey(); @@ -925,18 +927,6 @@ public String[] retrieveInterestingTerms(Reader r, String fieldName) throws IOEx return al.toArray(res); } - /** PriorityQueue that orders words by score. */ - private static class FreqQ extends PriorityQueue { - FreqQ(int maxSize) { - super(maxSize); - } - - @Override - protected boolean lessThan(ScoreTerm a, ScoreTerm b) { - return a.score < b.score; - } - } - private static class ScoreTerm { // only really need 1st 3 entries, other ones are for troubleshooting String word; diff --git a/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanOrQuery.java b/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanOrQuery.java index 46b14aef92dd..0acdd61f71e8 100644 --- a/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanOrQuery.java +++ b/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanOrQuery.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -31,6 +32,7 @@ import org.apache.lucene.search.ScoreMode; import org.apache.lucene.search.TwoPhaseIterator; import org.apache.lucene.search.Weight; +import org.apache.lucene.util.PriorityQueue; /** Matches the union of its clauses. */ public final class SpanOrQuery extends SpanQuery { @@ -187,8 +189,10 @@ public Spans getSpans(final LeafReaderContext context, Postings requiredPostings byDocQueue.add(new SpanDisiWrapper(spans)); } - SpanPositionQueue byPositionQueue = - new SpanPositionQueue(subSpans.size()); // when empty use -1 + PriorityQueue byPositionQueue = + PriorityQueue.usingComparator( + subSpans.size(), // when empty use -1 + Comparator.comparingInt(Spans::startPosition).thenComparingInt(Spans::endPosition)); return new Spans() { Spans topPositionSpans = null; diff --git a/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanPositionQueue.java b/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanPositionQueue.java deleted file mode 100644 index 49f079a39e28..000000000000 --- a/lucene/queries/src/java/org/apache/lucene/queries/spans/SpanPositionQueue.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.lucene.queries.spans; - -import org.apache.lucene.util.PriorityQueue; - -class SpanPositionQueue extends PriorityQueue { - SpanPositionQueue(int maxSize) { - super(maxSize); // do not prepopulate - } - - @Override - protected boolean lessThan(Spans s1, Spans s2) { - int start1 = s1.startPosition(); - int start2 = s2.startPosition(); - return (start1 < start2) - ? true - : (start1 == start2) ? s1.endPosition() < s2.endPosition() : false; - } -} diff --git a/lucene/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java b/lucene/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java index ce2a6fddbe32..e4663cb7e278 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java +++ b/lucene/sandbox/src/java/org/apache/lucene/sandbox/queries/FuzzyLikeThisQuery.java @@ -18,6 +18,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -45,6 +46,7 @@ import org.apache.lucene.search.similarities.ClassicSimilarity; import org.apache.lucene.search.similarities.TFIDFSimilarity; import org.apache.lucene.util.BytesRef; +import org.apache.lucene.util.FloatComparator; import org.apache.lucene.util.PriorityQueue; import org.apache.lucene.util.automaton.LevenshteinAutomata; @@ -189,7 +191,8 @@ public void addTerms( fieldVals.add(new FieldVals(fieldName, maxEdits, prefixLength, queryString)); } - private void addTerms(IndexReader reader, FieldVals f, ScoreTermQueue q) throws IOException { + private void addTerms(IndexReader reader, FieldVals f, PriorityQueue q) + throws IOException { if (f.queryString == null) return; final Terms terms = MultiTerms.getTerms(reader, f.fieldName); if (terms == null) { @@ -205,8 +208,8 @@ private void addTerms(IndexReader reader, FieldVals f, ScoreTermQueue q) throws String term = termAtt.toString(); if (!processedTerms.contains(term)) { processedTerms.add(term); - ScoreTermQueue variantsQ = - new ScoreTermQueue( + PriorityQueue variantsQ = + createScoreTermQueue( MAX_VARIANTS_PER_TERM); // maxNum variants considered for any one term float minScore = 0; Term startTerm = new Term(f.fieldName, term); @@ -282,7 +285,7 @@ public void visit(QueryVisitor visitor) { @Override public Query rewrite(IndexSearcher indexSearcher) throws IOException { IndexReader reader = indexSearcher.getIndexReader(); - ScoreTermQueue q = new ScoreTermQueue(maxNumTerms); + PriorityQueue q = createScoreTermQueue(maxNumTerms); // load up the list of possible terms for (FieldVals f : fieldVals) { addTerms(reader, f, q); @@ -347,20 +350,11 @@ public ScoreTerm(Term term, float score, Term fuzziedSourceTerm) { } } - private static class ScoreTermQueue extends PriorityQueue { - public ScoreTermQueue(int size) { - super(size); - } - - /* (non-Javadoc) - * @see org.apache.lucene.util.PriorityQueue#lessThan(java.lang.Object, java.lang.Object) - */ - @Override - protected boolean lessThan(ScoreTerm termA, ScoreTerm termB) { - if (termA.score == termB.score) { - return termA.term.compareTo(termB.term) > 0; - } else return termA.score < termB.score; - } + private static PriorityQueue createScoreTermQueue(int size) { + return PriorityQueue.usingComparator( + size, + FloatComparator.comparing(st -> st.score) + .thenComparing(st -> st.term, Comparator.reverseOrder())); } /* (non-Javadoc) diff --git a/lucene/sandbox/src/java/org/apache/lucene/sandbox/search/SortedNumericDocValuesMultiRangeQuery.java b/lucene/sandbox/src/java/org/apache/lucene/sandbox/search/SortedNumericDocValuesMultiRangeQuery.java index cc91d1f9a588..d6e679200af6 100644 --- a/lucene/sandbox/src/java/org/apache/lucene/sandbox/search/SortedNumericDocValuesMultiRangeQuery.java +++ b/lucene/sandbox/src/java/org/apache/lucene/sandbox/search/SortedNumericDocValuesMultiRangeQuery.java @@ -92,18 +92,10 @@ private static NavigableSet resolveOverlaps( // .thenComparing(r -> r.upper)// have to ignore upper boundary for .floor() lookups ); PriorityQueue heap = - new PriorityQueue<>(clauses.size() * 2) { - @Override - protected boolean lessThan(Edge a, Edge b) { - if (a.getValue() < b.getValue()) { - return true; - } else if (a.getValue() == b.getValue()) { - return a.point; // if a point is in the edge of the range, pass the point first - } else { - return false; - } - } - }; + PriorityQueue.usingComparator( + clauses.size() * 2, + Comparator.comparingLong(Edge::getValue) + .thenComparing(e -> e.point, Comparator.reverseOrder())); // points first for (DocValuesMultiRangeQuery.LongRange r : clauses) { long cmp = r.lower - r.upper; if (cmp == 0) {