From 4338aff4cb248fa955911f97027350d6ae863cdd Mon Sep 17 00:00:00 2001 From: easyice <80152403@qq.com> Date: Sun, 15 Mar 2026 21:19:09 +0800 Subject: [PATCH 1/2] Use ArrayUtil#copyOfSubArray to simplify manual array copy patterns --- .../blocktreeords/OrdsBlockTreeTermsWriter.java | 3 +-- .../lucene/codecs/memory/DirectPostingsFormat.java | 13 +++++-------- .../blocktree/Lucene103BlockTreeTermsWriter.java | 3 +-- .../apache/lucene/document/InetAddressRange.java | 7 +++---- .../java/org/apache/lucene/index/IndexingChain.java | 9 +++++---- .../lucene/search/DoubleValuesSourceRescorer.java | 4 +--- .../org/apache/lucene/search/QueryRescorer.java | 4 +--- .../java/org/apache/lucene/util/NumericUtils.java | 3 +-- .../src/java/org/apache/lucene/util/PagedBytes.java | 4 +--- .../apache/lucene/util/automaton/Operations.java | 4 +--- .../java/org/apache/lucene/util/hnsw/FloatHeap.java | 6 +++--- 11 files changed, 23 insertions(+), 37 deletions(-) diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/OrdsBlockTreeTermsWriter.java b/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/OrdsBlockTreeTermsWriter.java index 67f4a966b0f1..1584e32d849a 100644 --- a/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/OrdsBlockTreeTermsWriter.java +++ b/lucene/codecs/src/java/org/apache/lucene/codecs/blocktreeords/OrdsBlockTreeTermsWriter.java @@ -260,8 +260,7 @@ private static final class PendingTerm extends PendingEntry { public PendingTerm(BytesRef term, BlockTermState state) { super(true); - this.termBytes = new byte[term.length]; - System.arraycopy(term.bytes, term.offset, termBytes, 0, term.length); + this.termBytes = ArrayUtil.copyOfSubArray(term.bytes, term.offset, term.offset + term.length); this.state = state; } diff --git a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java index cbf6c7e660f7..2d1d012cc331 100644 --- a/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java +++ b/lucene/codecs/src/java/org/apache/lucene/codecs/memory/DirectPostingsFormat.java @@ -277,8 +277,7 @@ public void add(int value) { } public int[] get() { - final int[] arr = new int[upto]; - System.arraycopy(ints, 0, arr, 0, upto); + final int[] arr = ArrayUtil.copyOfSubArray(ints, 0, upto); upto = 0; return arr; } @@ -444,10 +443,9 @@ public DirectField( if (hasPayloads) { BytesRef payload = docsAndPositionsEnum.getPayload(); if (payload != null) { - byte[] payloadBytes = new byte[payload.length]; - System.arraycopy( - payload.bytes, payload.offset, payloadBytes, 0, payload.length); - payloads[upto][pos] = payloadBytes; + payloads[upto][pos] = + ArrayUtil.copyOfSubArray( + payload.bytes, payload.offset, payload.offset + payload.length); } } posUpto++; @@ -477,8 +475,7 @@ public DirectField( // System.out.println(skipCount + " skips: " + field); - this.termBytes = new byte[termOffset]; - System.arraycopy(termBytes, 0, this.termBytes, 0, termOffset); + this.termBytes = ArrayUtil.copyOfSubArray(termBytes, 0, termOffset); // Pack skips: this.skips = new int[skipCount]; diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene103/blocktree/Lucene103BlockTreeTermsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene103/blocktree/Lucene103BlockTreeTermsWriter.java index 1ce0ebd3509d..2ca29a37c288 100644 --- a/lucene/core/src/java/org/apache/lucene/codecs/lucene103/blocktree/Lucene103BlockTreeTermsWriter.java +++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene103/blocktree/Lucene103BlockTreeTermsWriter.java @@ -411,8 +411,7 @@ private static final class PendingTerm extends PendingEntry { public PendingTerm(BytesRef term, BlockTermState state) { super(true); - this.termBytes = new byte[term.length]; - System.arraycopy(term.bytes, term.offset, termBytes, 0, term.length); + this.termBytes = ArrayUtil.copyOfSubArray(term.bytes, term.offset, term.offset + term.length); this.state = state; } diff --git a/lucene/core/src/java/org/apache/lucene/document/InetAddressRange.java b/lucene/core/src/java/org/apache/lucene/document/InetAddressRange.java index 48edf68cada8..8817359b3f45 100644 --- a/lucene/core/src/java/org/apache/lucene/document/InetAddressRange.java +++ b/lucene/core/src/java/org/apache/lucene/document/InetAddressRange.java @@ -20,6 +20,7 @@ import java.util.Arrays; import org.apache.lucene.document.RangeFieldQuery.QueryType; import org.apache.lucene.search.Query; +import org.apache.lucene.util.ArrayUtil; import org.apache.lucene.util.BytesRef; /** @@ -182,10 +183,8 @@ protected String toString(byte[] ranges, int dimension) { * @return The string representation for the range at the provided dimension */ private static String toString(byte[] ranges, int dimension) { - byte[] min = new byte[BYTES]; - System.arraycopy(ranges, 0, min, 0, BYTES); - byte[] max = new byte[BYTES]; - System.arraycopy(ranges, BYTES, max, 0, BYTES); + byte[] min = ArrayUtil.copyOfSubArray(ranges, 0, BYTES); + byte[] max = ArrayUtil.copyOfSubArray(ranges, BYTES, BYTES + BYTES); return "[" + InetAddressPoint.decode(min) + " : " + InetAddressPoint.decode(max) + "]"; } } diff --git a/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java b/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java index 80d18cea435a..fd5be6254938 100644 --- a/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java +++ b/lucene/core/src/java/org/apache/lucene/index/IndexingChain.java @@ -1290,9 +1290,9 @@ private void invertTokenStream(int docID, IndexableField field, boolean first) try { termsHashPerField.add(invertState.termAttribute.getBytesRef(), docID); } catch (MaxBytesLengthExceededException e) { - byte[] prefix = new byte[30]; BytesRef bigTerm = invertState.termAttribute.getBytesRef(); - System.arraycopy(bigTerm.bytes, bigTerm.offset, prefix, 0, 30); + byte[] prefix = + ArrayUtil.copyOfSubArray(bigTerm.bytes, bigTerm.offset, bigTerm.offset + 30); String msg = "Document contains at least one immense term in field=\"" + fieldInfo.name @@ -1363,8 +1363,9 @@ private void invertTerm(int docID, IndexableField field, boolean first) throws I try { termsHashPerField.add(binaryValue, docID); } catch (MaxBytesLengthExceededException e) { - byte[] prefix = new byte[30]; - System.arraycopy(binaryValue.bytes, binaryValue.offset, prefix, 0, 30); + byte[] prefix = + ArrayUtil.copyOfSubArray( + binaryValue.bytes, binaryValue.offset, binaryValue.offset + 30); String msg = "Document contains at least one immense term in field=\"" + fieldInfo.name diff --git a/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSourceRescorer.java b/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSourceRescorer.java index 8b1cb3445495..cc60a566c140 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSourceRescorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DoubleValuesSourceRescorer.java @@ -78,9 +78,7 @@ public TopDocs rescore(IndexSearcher searcher, TopDocs firstPassTopDocs, int top if (topN < hits.length) { ArrayUtil.select(hits, 0, hits.length, topN, ScoreDoc.COMPARATOR); - ScoreDoc[] subset = new ScoreDoc[topN]; - System.arraycopy(hits, 0, subset, 0, topN); - hits = subset; + hits = ArrayUtil.copyOfSubArray(hits, 0, topN); } Arrays.sort(hits, ScoreDoc.COMPARATOR); diff --git a/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java b/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java index 27d88504b30b..d818da08aedb 100644 --- a/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/QueryRescorer.java @@ -119,9 +119,7 @@ public TopDocs rescore(IndexSearcher searcher, TopDocs firstPassTopDocs, int top if (topN < hits.length) { ArrayUtil.select(hits, 0, hits.length, topN, sortDocComparator); - ScoreDoc[] subset = new ScoreDoc[topN]; - System.arraycopy(hits, 0, subset, 0, topN); - hits = subset; + hits = ArrayUtil.copyOfSubArray(hits, 0, topN); } Arrays.sort(hits, sortDocComparator); diff --git a/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java b/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java index 6fd711a4ba43..2d2d971056bb 100644 --- a/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java +++ b/lucene/core/src/java/org/apache/lucene/util/NumericUtils.java @@ -257,8 +257,7 @@ assert sortableBytesToBigInt(result, offset, bigIntSize).equals(bigInt) * @see #bigIntToSortableBytes(BigInteger, int, byte[], int) */ public static BigInteger sortableBytesToBigInt(byte[] encoded, int offset, int length) { - byte[] bigIntBytes = new byte[length]; - System.arraycopy(encoded, offset, bigIntBytes, 0, length); + byte[] bigIntBytes = ArrayUtil.copyOfSubArray(encoded, offset, offset + length); // Flip the sign bit back to the original bigIntBytes[0] ^= 0x80; return new BigInteger(bigIntBytes); diff --git a/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java b/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java index e63b75418f93..7babf031d1e8 100644 --- a/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java +++ b/lucene/core/src/java/org/apache/lucene/util/PagedBytes.java @@ -226,9 +226,7 @@ public Reader freeze(boolean trim) { throw new IllegalStateException("cannot freeze when copy(BytesRef, BytesRef) was used"); } if (trim && upto < blockSize) { - final byte[] newBlock = new byte[upto]; - System.arraycopy(currentBlock, 0, newBlock, 0, upto); - currentBlock = newBlock; + currentBlock = ArrayUtil.copyOfSubArray(currentBlock, 0, upto); } if (currentBlock == null) { currentBlock = EMPTY_BYTES; diff --git a/lucene/core/src/java/org/apache/lucene/util/automaton/Operations.java b/lucene/core/src/java/org/apache/lucene/util/automaton/Operations.java index 8c7185393f65..925201b2c5d1 100644 --- a/lucene/core/src/java/org/apache/lucene/util/automaton/Operations.java +++ b/lucene/core/src/java/org/apache/lucene/util/automaton/Operations.java @@ -1372,9 +1372,7 @@ public static int[] topoSortStates(Automaton a) { if (upto < states.length) { // There were dead states - int[] newStates = new int[upto]; - System.arraycopy(states, 0, newStates, 0, upto); - states = newStates; + states = ArrayUtil.copyOfSubArray(states, 0, upto); } // Reverse the order: diff --git a/lucene/core/src/java/org/apache/lucene/util/hnsw/FloatHeap.java b/lucene/core/src/java/org/apache/lucene/util/hnsw/FloatHeap.java index e1a267a3c015..dd86f8632b8d 100644 --- a/lucene/core/src/java/org/apache/lucene/util/hnsw/FloatHeap.java +++ b/lucene/core/src/java/org/apache/lucene/util/hnsw/FloatHeap.java @@ -17,6 +17,8 @@ package org.apache.lucene.util.hnsw; +import org.apache.lucene.util.ArrayUtil; + /** * A bounded min heap that stores floats. The top element is the lowest value of the heap. * @@ -59,9 +61,7 @@ public boolean offer(float value) { } public float[] getHeap() { - float[] result = new float[size]; - System.arraycopy(this.heap, 1, result, 0, size); - return result; + return ArrayUtil.copyOfSubArray(this.heap, 1, 1 + size); } /** From 955f919c58ba293d249da970c30646c99bbc57f6 Mon Sep 17 00:00:00 2001 From: easyice <80152403@qq.com> Date: Mon, 16 Mar 2026 15:27:23 +0800 Subject: [PATCH 2/2] add changes entry --- lucene/CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index 9db4d195d4ba..8a9fd8d43a60 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -281,6 +281,8 @@ Other * GITHUB#15799: Exclude JNA Cleaner from thread leak detection by LuceneTestCase. (Alan Woodward) +* GITHUB#15826: Use ArrayUtil#copyOfSubArray to simplify manual array copy patterns. (Zhang Chao) + ======================= Lucene 10.4.0 ======================= API Changes