From 3969be03c9c36ca5a0e741d9fc845a4934599443 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 4 Feb 2025 15:45:28 +0100 Subject: [PATCH] Polishing. Introduce empty constants to reduce allocations. See #3193 Original pull request: #3194 --- .../data/domain/DoubleVector.java | 23 ++++++++++++++++--- .../data/domain/FloatVector.java | 23 ++++++++++++++++--- .../data/domain/NumberVector.java | 22 ++++++++++++++++-- .../springframework/data/domain/Vector.java | 9 ++++++-- 4 files changed, 67 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/springframework/data/domain/DoubleVector.java b/src/main/java/org/springframework/data/domain/DoubleVector.java index b3669c4f7..ddd9b4914 100644 --- a/src/main/java/org/springframework/data/domain/DoubleVector.java +++ b/src/main/java/org/springframework/data/domain/DoubleVector.java @@ -24,11 +24,26 @@ import org.springframework.util.ObjectUtils; * {@link Vector} implementation based on {@code double} array. * * @author Mark Paluch + * @author Christoph Strobl * @since 3.5 */ class DoubleVector implements Vector { - private final double[] v; + static final DoubleVector EMPTY = new DoubleVector(new double[0]) { + + @Override + public float[] toFloatArray() { + return FloatVector.EMPTY.v; + } + + @Override + public double[] toDoubleArray() { + return this.v; + } + + }; + + final double[] v; DoubleVector(double[] v) { this.v = v; @@ -40,7 +55,7 @@ class DoubleVector implements Vector { static Vector copy(double[] v) { if (v.length == 0) { - return new DoubleVector(new double[0]); + return EMPTY; } return new DoubleVector(Arrays.copyOf(v, v.length)); @@ -52,7 +67,7 @@ class DoubleVector implements Vector { static Vector copy(Collection v) { if (v.isEmpty()) { - return new DoubleVector(new double[0]); + return EMPTY; } double[] copy = new double[v.size()]; @@ -101,9 +116,11 @@ class DoubleVector implements Vector { if (this == o) { return true; } + if (!(o instanceof DoubleVector that)) { return false; } + return ObjectUtils.nullSafeEquals(v, that.v); } diff --git a/src/main/java/org/springframework/data/domain/FloatVector.java b/src/main/java/org/springframework/data/domain/FloatVector.java index d2d85f438..ac1be1e16 100644 --- a/src/main/java/org/springframework/data/domain/FloatVector.java +++ b/src/main/java/org/springframework/data/domain/FloatVector.java @@ -24,11 +24,26 @@ import org.springframework.util.ObjectUtils; * {@link Vector} implementation based on {@code float} array. * * @author Mark Paluch + * @author Christoph Strobl * @since 3.5 */ class FloatVector implements Vector { - private final float[] v; + static final FloatVector EMPTY = new FloatVector(new float[0]) { + + @Override + public float[] toFloatArray() { + return this.v; + } + + @Override + public double[] toDoubleArray() { + return DoubleVector.EMPTY.v; + } + + }; + + final float[] v; FloatVector(float[] v) { this.v = v; @@ -40,7 +55,7 @@ class FloatVector implements Vector { static Vector copy(float[] v) { if (v.length == 0) { - return new FloatVector(new float[0]); + return EMPTY; } return new FloatVector(Arrays.copyOf(v, v.length)); @@ -52,7 +67,7 @@ class FloatVector implements Vector { static Vector copy(Collection v) { if (v.isEmpty()) { - return new FloatVector(new float[0]); + return EMPTY; } float[] copy = new float[v.size()]; @@ -101,9 +116,11 @@ class FloatVector implements Vector { if (this == o) { return true; } + if (!(o instanceof FloatVector that)) { return false; } + return ObjectUtils.nullSafeEquals(v, that.v); } diff --git a/src/main/java/org/springframework/data/domain/NumberVector.java b/src/main/java/org/springframework/data/domain/NumberVector.java index 528916e86..40d9ad3cf 100644 --- a/src/main/java/org/springframework/data/domain/NumberVector.java +++ b/src/main/java/org/springframework/data/domain/NumberVector.java @@ -25,10 +25,25 @@ import org.springframework.util.ObjectUtils; * {@link Vector} implementation based on {@link Number} array. * * @author Mark Paluch + * @author Christoph Strobl * @since 3.5 */ class NumberVector implements Vector { + static final NumberVector EMPTY = new NumberVector(new Number[0]) { + + @Override + public float[] toFloatArray() { + return FloatVector.EMPTY.v; + } + + @Override + public double[] toDoubleArray() { + return DoubleVector.EMPTY.v; + } + + }; + private final Number[] v; NumberVector(Number[] v) { @@ -43,7 +58,7 @@ class NumberVector implements Vector { static Vector copy(Number[] v) { if (v.length == 0) { - return new NumberVector(new Number[0]); + return EMPTY; } return new NumberVector(Arrays.copyOf(v, v.length)); @@ -55,7 +70,7 @@ class NumberVector implements Vector { static Vector copy(Collection v) { if (v.isEmpty()) { - return new NumberVector(new Number[0]); + return EMPTY; } return new NumberVector(v.toArray(Number[]::new)); @@ -74,6 +89,7 @@ class NumberVector implements Vector { return Number.class; } } + return candidate; } @@ -115,9 +131,11 @@ class NumberVector implements Vector { if (this == o) { return true; } + if (!(o instanceof NumberVector that)) { return false; } + return ObjectUtils.nullSafeEquals(v, that.v); } diff --git a/src/main/java/org/springframework/data/domain/Vector.java b/src/main/java/org/springframework/data/domain/Vector.java index db434e0f7..8743a2d2c 100644 --- a/src/main/java/org/springframework/data/domain/Vector.java +++ b/src/main/java/org/springframework/data/domain/Vector.java @@ -75,8 +75,9 @@ public interface Vector { static Vector of(Collection values) { Assert.notNull(values, "Vector values must not be null"); - if(values.isEmpty()) { - return NumberVector.copy(new Number[0]); + + if (values.isEmpty()) { + return NumberVector.EMPTY; } Class cet = CollectionUtils.findCommonElementType(values); @@ -152,6 +153,8 @@ public interface Vector { *

* Conversion to {@code float} can incorporate loss of precision or result in values with a slight offset due to data * type conversion if the source is not a {@code float} array. + *

+ * Note that Vectors using quantization or binary representations may not be convertible to a {@code float} array. * * @return a new {@code float} array representing the vector point. */ @@ -163,6 +166,8 @@ public interface Vector { *

* Conversion to {@code double} can incorporate loss of precision or result in values with a slight offset due to data * type conversion if the source is not a {@code double} array. + *

+ * Note that Vectors using quantization or binary representations may not be convertible to a {@code double} array. * * @return a new {@code double} array representing the vector point. */