This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new 3db62050da GH-37701: [Java] Add default comparators for more types 
(#37748)
3db62050da is described below

commit 3db62050daa67b927810574dea60fd5b84bcb523
Author: James Duong <[email protected]>
AuthorDate: Fri Sep 15 14:45:08 2023 -0700

    GH-37701: [Java] Add default comparators for more types (#37748)
    
    ### Rationale for this change
    
    Add default comparators for more vector types to make algorithms easier to 
use and provide more consistency for Java compared to other languages.
    
    ### What changes are included in this PR?
    
    Add default type comparators for:
    - BitVector
    - DateDayVector
    - DateMilliVector
    - Decimal256Vector
    - DecimalVector
    - DurationVector
    - IntervalDayVector
    - TimeMicroVector
    - TimeMilliVector
    - TimeNanoVector
    - TimeSecVector
    - TimeStampVector
    
    IntervalMonthDayNanoVector is not supported due to its public type 
PeriodDuration not being Comparable.
    BitVector's getWidth() method does not return valid data by design since 
its length is smaller than 1 byte. Using a BitVector with a fixed-width type's 
algorithm will throw an IllegalArgumentException.
    
    ### Are these changes tested?
    
    Yes.
    
    ### Are there any user-facing changes?
    
    No.
    * Closes: #37701
    
    Authored-by: James Duong <[email protected]>
    Signed-off-by: David Li <[email protected]>
---
 .../algorithm/sort/DefaultVectorComparators.java   | 329 +++++++++++++++
 .../sort/FixedWidthOutOfPlaceVectorSorter.java     |   4 +
 .../sort/TestDefaultVectorComparator.java          | 447 +++++++++++++++++++++
 .../org/apache/arrow/vector/Decimal256Vector.java  |  12 +-
 .../org/apache/arrow/vector/DecimalVector.java     |  12 +-
 .../org/apache/arrow/vector/DurationVector.java    |  14 +-
 .../org/apache/arrow/vector/IntervalDayVector.java |  18 +-
 .../vector/testing/ValueVectorDataPopulator.java   |  30 ++
 8 files changed, 858 insertions(+), 8 deletions(-)

diff --git 
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
 
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
index c418219170..99d66f9426 100644
--- 
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
+++ 
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/DefaultVectorComparators.java
@@ -19,15 +19,31 @@ package org.apache.arrow.algorithm.sort;
 
 import static 
org.apache.arrow.vector.complex.BaseRepeatedValueVector.OFFSET_WIDTH;
 
+import java.math.BigDecimal;
+import java.time.Duration;
+
 import org.apache.arrow.memory.util.ArrowBufPointer;
 import org.apache.arrow.memory.util.ByteFunctionHelpers;
 import org.apache.arrow.vector.BaseFixedWidthVector;
 import org.apache.arrow.vector.BaseVariableWidthVector;
 import org.apache.arrow.vector.BigIntVector;
+import org.apache.arrow.vector.BitVector;
+import org.apache.arrow.vector.DateDayVector;
+import org.apache.arrow.vector.DateMilliVector;
+import org.apache.arrow.vector.Decimal256Vector;
+import org.apache.arrow.vector.DecimalVector;
+import org.apache.arrow.vector.DurationVector;
 import org.apache.arrow.vector.Float4Vector;
 import org.apache.arrow.vector.Float8Vector;
 import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.IntervalDayVector;
+import org.apache.arrow.vector.IntervalMonthDayNanoVector;
 import org.apache.arrow.vector.SmallIntVector;
+import org.apache.arrow.vector.TimeMicroVector;
+import org.apache.arrow.vector.TimeMilliVector;
+import org.apache.arrow.vector.TimeNanoVector;
+import org.apache.arrow.vector.TimeSecVector;
+import org.apache.arrow.vector.TimeStampVector;
 import org.apache.arrow.vector.TinyIntVector;
 import org.apache.arrow.vector.UInt1Vector;
 import org.apache.arrow.vector.UInt2Vector;
@@ -69,6 +85,32 @@ public class DefaultVectorComparators {
         return (VectorValueComparator<T>) new UInt4Comparator();
       } else if (vector instanceof UInt8Vector) {
         return (VectorValueComparator<T>) new UInt8Comparator();
+      } else if (vector instanceof BitVector) {
+        return (VectorValueComparator<T>) new BitComparator();
+      } else if (vector instanceof DateDayVector) {
+        return (VectorValueComparator<T>) new DateDayComparator();
+      } else if (vector instanceof DateMilliVector) {
+        return (VectorValueComparator<T>) new DateMilliComparator();
+      } else if (vector instanceof Decimal256Vector) {
+        return (VectorValueComparator<T>) new Decimal256Comparator();
+      } else if (vector instanceof DecimalVector) {
+        return (VectorValueComparator<T>) new DecimalComparator();
+      } else if (vector instanceof DurationVector) {
+        return (VectorValueComparator<T>) new DurationComparator();
+      } else if (vector instanceof IntervalDayVector) {
+        return (VectorValueComparator<T>) new IntervalDayComparator();
+      } else if (vector instanceof IntervalMonthDayNanoVector) {
+        throw new IllegalArgumentException("No default comparator for " + 
vector.getClass().getCanonicalName());
+      } else if (vector instanceof TimeMicroVector) {
+        return (VectorValueComparator<T>) new TimeMicroComparator();
+      } else if (vector instanceof TimeMilliVector) {
+        return (VectorValueComparator<T>) new TimeMilliComparator();
+      } else if (vector instanceof TimeNanoVector) {
+        return (VectorValueComparator<T>) new TimeNanoComparator();
+      } else if (vector instanceof TimeSecVector) {
+        return (VectorValueComparator<T>) new TimeSecComparator();
+      } else if (vector instanceof TimeStampVector) {
+        return (VectorValueComparator<T>) new TimeStampComparator();
       }
     } else if (vector instanceof BaseVariableWidthVector) {
       return (VectorValueComparator<T>) new VariableWidthComparator();
@@ -345,6 +387,293 @@ public class DefaultVectorComparators {
     }
   }
 
+  /**
+   * Default comparator for bit type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class BitComparator extends VectorValueComparator<BitVector> {
+
+    public BitComparator() {
+      super(-1);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      boolean value1 = vector1.get(index1) != 0;
+      boolean value2 = vector2.get(index2) != 0;
+
+      return Boolean.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<BitVector> createNew() {
+      return new BitComparator();
+    }
+  }
+
+  /**
+   * Default comparator for DateDay type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class DateDayComparator extends 
VectorValueComparator<DateDayVector> {
+
+    public DateDayComparator() {
+      super(DateDayVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      int value1 = vector1.get(index1);
+      int value2 = vector2.get(index2);
+      return Integer.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<DateDayVector> createNew() {
+      return new DateDayComparator();
+    }
+  }
+
+  /**
+   * Default comparator for DateMilli type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class DateMilliComparator extends 
VectorValueComparator<DateMilliVector> {
+
+    public DateMilliComparator() {
+      super(DateMilliVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      long value1 = vector1.get(index1);
+      long value2 = vector2.get(index2);
+
+      return Long.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<DateMilliVector> createNew() {
+      return new DateMilliComparator();
+    }
+  }
+
+  /**
+   * Default comparator for Decimal256 type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class Decimal256Comparator extends 
VectorValueComparator<Decimal256Vector> {
+
+    public Decimal256Comparator() {
+      super(Decimal256Vector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      BigDecimal value1 = vector1.getObjectNotNull(index1);
+      BigDecimal value2 = vector2.getObjectNotNull(index2);
+
+      return value1.compareTo(value2);
+    }
+
+    @Override
+    public VectorValueComparator<Decimal256Vector> createNew() {
+      return new Decimal256Comparator();
+    }
+  }
+
+  /**
+   * Default comparator for Decimal type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class DecimalComparator extends 
VectorValueComparator<DecimalVector> {
+
+    public DecimalComparator() {
+      super(DecimalVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      BigDecimal value1 = vector1.getObjectNotNull(index1);
+      BigDecimal value2 = vector2.getObjectNotNull(index2);
+
+      return value1.compareTo(value2);
+    }
+
+    @Override
+    public VectorValueComparator<DecimalVector> createNew() {
+      return new DecimalComparator();
+    }
+  }
+
+  /**
+   * Default comparator for Duration type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class DurationComparator extends 
VectorValueComparator<DurationVector> {
+
+    public DurationComparator() {
+      super(DurationVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      Duration value1 = vector1.getObjectNotNull(index1);
+      Duration value2 = vector2.getObjectNotNull(index2);
+
+      return value1.compareTo(value2);
+    }
+
+    @Override
+    public VectorValueComparator<DurationVector> createNew() {
+      return new DurationComparator();
+    }
+  }
+
+  /**
+   * Default comparator for IntervalDay type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class IntervalDayComparator extends 
VectorValueComparator<IntervalDayVector> {
+
+    public IntervalDayComparator() {
+      super(IntervalDayVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      Duration value1 = vector1.getObjectNotNull(index1);
+      Duration value2 = vector2.getObjectNotNull(index2);
+
+      return value1.compareTo(value2);
+    }
+
+    @Override
+    public VectorValueComparator<IntervalDayVector> createNew() {
+      return new IntervalDayComparator();
+    }
+  }
+
+  /**
+   * Default comparator for TimeMicro type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class TimeMicroComparator extends 
VectorValueComparator<TimeMicroVector> {
+
+    public TimeMicroComparator() {
+      super(TimeMicroVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      long value1 = vector1.get(index1);
+      long value2 = vector2.get(index2);
+
+      return Long.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<TimeMicroVector> createNew() {
+      return new TimeMicroComparator();
+    }
+  }
+
+  /**
+   * Default comparator for TimeMilli type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class TimeMilliComparator extends 
VectorValueComparator<TimeMilliVector> {
+
+    public TimeMilliComparator() {
+      super(TimeMilliVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      int value1 = vector1.get(index1);
+      int value2 = vector2.get(index2);
+
+      return Integer.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<TimeMilliVector> createNew() {
+      return new TimeMilliComparator();
+    }
+  }
+
+  /**
+   * Default comparator for TimeNano type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class TimeNanoComparator extends 
VectorValueComparator<TimeNanoVector> {
+
+    public TimeNanoComparator() {
+      super(TimeNanoVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      long value1 = vector1.get(index1);
+      long value2 = vector2.get(index2);
+
+      return Long.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<TimeNanoVector> createNew() {
+      return new TimeNanoComparator();
+    }
+  }
+
+  /**
+   * Default comparator for TimeSec type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class TimeSecComparator extends 
VectorValueComparator<TimeSecVector> {
+
+    public TimeSecComparator() {
+      super(TimeSecVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      int value1 = vector1.get(index1);
+      int value2 = vector2.get(index2);
+
+      return Integer.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<TimeSecVector> createNew() {
+      return new TimeSecComparator();
+    }
+  }
+
+  /**
+   * Default comparator for TimeSec type.
+   * The comparison is based on values, with null comes first.
+   */
+  public static class TimeStampComparator extends 
VectorValueComparator<TimeStampVector> {
+
+    public TimeStampComparator() {
+      super(TimeStampVector.TYPE_WIDTH);
+    }
+
+    @Override
+    public int compareNotNull(int index1, int index2) {
+      long value1 = vector1.get(index1);
+      long value2 = vector2.get(index2);
+
+      return Long.compare(value1, value2);
+    }
+
+    @Override
+    public VectorValueComparator<TimeStampVector> createNew() {
+      return new TimeStampComparator();
+    }
+  }
+
   /**
    * Default comparator for {@link 
org.apache.arrow.vector.BaseVariableWidthVector}.
    * The comparison is in lexicographic order, with null comes first.
diff --git 
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
 
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
index 43d604060d..c3b68facfd 100644
--- 
a/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
+++ 
b/java/algorithm/src/main/java/org/apache/arrow/algorithm/sort/FixedWidthOutOfPlaceVectorSorter.java
@@ -21,6 +21,7 @@ import org.apache.arrow.memory.ArrowBuf;
 import org.apache.arrow.memory.util.MemoryUtil;
 import org.apache.arrow.util.Preconditions;
 import org.apache.arrow.vector.BaseFixedWidthVector;
+import org.apache.arrow.vector.BitVector;
 import org.apache.arrow.vector.BitVectorHelper;
 import org.apache.arrow.vector.IntVector;
 
@@ -35,6 +36,9 @@ public class FixedWidthOutOfPlaceVectorSorter<V extends 
BaseFixedWidthVector> im
 
   @Override
   public void sortOutOfPlace(V srcVector, V dstVector, 
VectorValueComparator<V> comparator) {
+    if (srcVector instanceof BitVector) {
+      throw new IllegalArgumentException("BitVector is not supported with 
FixedWidthOutOfPlaceVectorSorter.");
+    }
     comparator.attachVector(srcVector);
 
     int valueWidth = comparator.getValueWidth();
diff --git 
a/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
 
b/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
index 818bb60d11..6205119774 100644
--- 
a/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
+++ 
b/java/algorithm/src/test/java/org/apache/arrow/algorithm/sort/TestDefaultVectorComparator.java
@@ -25,8 +25,23 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import org.apache.arrow.memory.BufferAllocator;
 import org.apache.arrow.memory.RootAllocator;
 import org.apache.arrow.vector.BigIntVector;
+import org.apache.arrow.vector.BitVector;
+import org.apache.arrow.vector.DateDayVector;
+import org.apache.arrow.vector.DateMilliVector;
+import org.apache.arrow.vector.Decimal256Vector;
+import org.apache.arrow.vector.DecimalVector;
+import org.apache.arrow.vector.DurationVector;
+import org.apache.arrow.vector.Float4Vector;
+import org.apache.arrow.vector.Float8Vector;
 import org.apache.arrow.vector.IntVector;
+import org.apache.arrow.vector.IntervalDayVector;
 import org.apache.arrow.vector.SmallIntVector;
+import org.apache.arrow.vector.TimeMicroVector;
+import org.apache.arrow.vector.TimeMilliVector;
+import org.apache.arrow.vector.TimeNanoVector;
+import org.apache.arrow.vector.TimeSecVector;
+import org.apache.arrow.vector.TimeStampMilliVector;
+import org.apache.arrow.vector.TimeStampVector;
 import org.apache.arrow.vector.TinyIntVector;
 import org.apache.arrow.vector.UInt1Vector;
 import org.apache.arrow.vector.UInt2Vector;
@@ -34,6 +49,7 @@ import org.apache.arrow.vector.UInt4Vector;
 import org.apache.arrow.vector.UInt8Vector;
 import org.apache.arrow.vector.complex.ListVector;
 import org.apache.arrow.vector.testing.ValueVectorDataPopulator;
+import org.apache.arrow.vector.types.TimeUnit;
 import org.apache.arrow.vector.types.Types;
 import org.apache.arrow.vector.types.pojo.ArrowType;
 import org.apache.arrow.vector.types.pojo.FieldType;
@@ -271,6 +287,76 @@ public class TestDefaultVectorComparator {
     }
   }
 
+  @Test
+  public void testCompareFloat4() {
+    try (Float4Vector vec = new Float4Vector("", allocator)) {
+      vec.allocateNew(9);
+      ValueVectorDataPopulator.setVector(
+          vec, -1.1f, 0.0f, 1.0f, null, 1.0f, 2.0f, Float.NaN, Float.NaN, 
Float.POSITIVE_INFINITY,
+          Float.NEGATIVE_INFINITY);
+
+      VectorValueComparator<Float4Vector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+      assertTrue(comparator.compare(8, 3) > 0);
+
+      // NaN behavior.
+      assertTrue(comparator.compare(6, 7) == 0);
+      assertTrue(comparator.compare(7, 6) == 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+      assertTrue(comparator.compare(6, 0) > 0);
+      assertTrue(comparator.compare(6, 8) > 0);
+      assertTrue(comparator.compare(6, 3) > 0);
+    }
+  }
+
+  @Test
+  public void testCompareFloat8() {
+    try (Float8Vector vec = new Float8Vector("", allocator)) {
+      vec.allocateNew(9);
+      ValueVectorDataPopulator.setVector(
+          vec, -1.1, 0.0, 1.0, null, 1.0, 2.0, Double.NaN, Double.NaN, 
Double.POSITIVE_INFINITY,
+          Double.NEGATIVE_INFINITY);
+
+      VectorValueComparator<Float8Vector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+      assertTrue(comparator.compare(8, 3) > 0);
+
+      // NaN behavior.
+      assertTrue(comparator.compare(6, 7) == 0);
+      assertTrue(comparator.compare(7, 6) == 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+      assertTrue(comparator.compare(6, 0) > 0);
+      assertTrue(comparator.compare(6, 8) > 0);
+      assertTrue(comparator.compare(6, 3) > 0);
+    }
+  }
+
   @Test
   public void testCompareLong() {
     try (BigIntVector vec = new BigIntVector("", allocator)) {
@@ -393,6 +479,367 @@ public class TestDefaultVectorComparator {
     }
   }
 
+  @Test
+  public void testCompareBit() {
+    try (BitVector vec = new BitVector("", allocator)) {
+      vec.allocateNew(6);
+      ValueVectorDataPopulator.setVector(
+          vec, 1, 2, 0, 0, -1, null);
+
+      VectorValueComparator<BitVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) == 0);
+      assertTrue(comparator.compare(0, 2) > 0);
+      assertTrue(comparator.compare(0, 4) == 0);
+      assertTrue(comparator.compare(2, 1) < 0);
+      assertTrue(comparator.compare(2, 4) < 0);
+
+      // null first
+      assertTrue(comparator.compare(5, 0) < 0);
+      assertTrue(comparator.compare(5, 2) < 0);
+    }
+  }
+
+  @Test
+  public void testCompareDateDay() {
+    try (DateDayVector vec = new DateDayVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1, 0, 1, null, 1, 5, Integer.MIN_VALUE + 1, Integer.MAX_VALUE);
+
+      VectorValueComparator<DateDayVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareDateMilli() {
+    try (DateMilliVector vec = new DateMilliVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<DateMilliVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareDecimal() {
+    try (DecimalVector vec = new DecimalVector("", allocator, 10, 1)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<DecimalVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareDecimal256() {
+    try (Decimal256Vector vec = new Decimal256Vector("", allocator, 10, 1)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<Decimal256Vector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareDuration() {
+    try (DurationVector vec =
+             new DurationVector("", FieldType.nullable(new 
ArrowType.Duration(TimeUnit.MILLISECOND)), allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<DurationVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareIntervalDay() {
+    try (IntervalDayVector vec =
+             new IntervalDayVector("", FieldType.nullable(new 
ArrowType.Duration(TimeUnit.MILLISECOND)), allocator)) {
+      vec.allocateNew(8);
+      vec.set(0, -1, 0);
+      vec.set(1, 0, 0);
+      vec.set(2, 1, 0);
+      vec.setNull(3);
+      vec.set(4, -1, -1);
+      vec.set(5, 1, 1);
+      vec.set(6, 1, 1);
+      vec.set(7, -1, -1);
+
+      VectorValueComparator<IntervalDayVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+      assertTrue(comparator.compare(2, 5) < 0);
+      assertTrue(comparator.compare(0, 4) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 6) == 0);
+      assertTrue(comparator.compare(4, 7) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+    }
+  }
+
+  @Test
+  public void testCompareTimeMicro() {
+    try (TimeMicroVector vec =
+             new TimeMicroVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<TimeMicroVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareTimeMilli() {
+    try (TimeMilliVector vec = new TimeMilliVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1, 0, 1, null, 1, 5, Integer.MIN_VALUE + 1, Integer.MAX_VALUE);
+
+      VectorValueComparator<TimeMilliVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareTimeNano() {
+    try (TimeNanoVector vec =
+             new TimeNanoVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<TimeNanoVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareTimeSec() {
+    try (TimeSecVector vec = new TimeSecVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1, 0, 1, null, 1, 5, Integer.MIN_VALUE + 1, Integer.MAX_VALUE);
+
+      VectorValueComparator<TimeSecVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
+  @Test
+  public void testCompareTimeStamp() {
+    try (TimeStampMilliVector vec =
+             new TimeStampMilliVector("", allocator)) {
+      vec.allocateNew(8);
+      ValueVectorDataPopulator.setVector(
+          vec, -1L, 0L, 1L, null, 1L, 5L, Long.MIN_VALUE + 1L, Long.MAX_VALUE);
+
+      VectorValueComparator<TimeStampVector> comparator =
+          DefaultVectorComparators.createDefaultComparator(vec);
+      comparator.attachVector(vec);
+
+      assertTrue(comparator.compare(0, 1) < 0);
+      assertTrue(comparator.compare(0, 2) < 0);
+      assertTrue(comparator.compare(2, 1) > 0);
+
+      // test equality
+      assertTrue(comparator.compare(5, 5) == 0);
+      assertTrue(comparator.compare(2, 4) == 0);
+
+      // null first
+      assertTrue(comparator.compare(3, 4) < 0);
+      assertTrue(comparator.compare(5, 3) > 0);
+
+      // potential overflow
+      assertTrue(comparator.compare(6, 7) < 0);
+      assertTrue(comparator.compare(7, 6) > 0);
+      assertTrue(comparator.compare(7, 7) == 0);
+    }
+  }
+
   @Test
   public void testCheckNullsOnCompareIsFalseForNonNullableVector() {
     try (IntVector vec = new IntVector("not nullable",
diff --git 
a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java 
b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
index 4ccee50d68..70a895ff40 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
@@ -154,10 +154,20 @@ public final class Decimal256Vector extends 
BaseFixedWidthVector {
     if (isSet(index) == 0) {
       return null;
     } else {
-      return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, 
scale, TYPE_WIDTH);
+      return getObjectNotNull(index);
     }
   }
 
+  /**
+   * Same as {@link #getObject(int)}, but does not check for null.
+   *
+   * @param index   position of element
+   * @return element at given index
+   */
+  public BigDecimal getObjectNotNull(int index) {
+    return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, scale, 
TYPE_WIDTH);
+  }
+
   /**
    * Return precision for the decimal value.
    */
diff --git 
a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java 
b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
index db04563df2..6a3ec60afc 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
@@ -153,10 +153,20 @@ public final class DecimalVector extends 
BaseFixedWidthVector {
     if (isSet(index) == 0) {
       return null;
     } else {
-      return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, 
scale, TYPE_WIDTH);
+      return getObjectNotNull(index);
     }
   }
 
+  /**
+   * Same as {@link #getObect(int)} but does not check for null.
+   *
+   * @param index   position of element
+   * @return element at given index
+   */
+  public BigDecimal getObjectNotNull(int index) {
+    return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, scale, 
TYPE_WIDTH);
+  }
+
   /**
    * Return precision for the decimal value.
    */
diff --git 
a/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java 
b/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
index 1e1db0d1c3..b6abc16194 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
@@ -147,11 +147,21 @@ public final class DurationVector extends 
BaseFixedWidthVector {
     if (isSet(index) == 0) {
       return null;
     } else {
-      final long value = get(valueBuffer, index);
-      return toDuration(value, unit);
+      return getObjectNotNull(index);
     }
   }
 
+  /**
+   * Same as {@link #getObject(int)} but does not check for null.
+   *
+   * @param index   position of element
+   * @return element at given index
+   */
+  public Duration getObjectNotNull(int index) {
+    final long value = get(valueBuffer, index);
+    return toDuration(value, unit);
+  }
+
   /**
    * Converts the given value and unit to the appropriate {@link Duration}.
    */
diff --git 
a/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java 
b/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
index 35312ba7c9..7c0d19baa9 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
@@ -168,13 +168,23 @@ public final class IntervalDayVector extends 
BaseFixedWidthVector {
     if (isSet(index) == 0) {
       return null;
     } else {
-      final long startIndex = (long) index * TYPE_WIDTH;
-      final int days = valueBuffer.getInt(startIndex);
-      final int milliseconds = valueBuffer.getInt(startIndex + 
MILLISECOND_OFFSET);
-      return Duration.ofDays(days).plusMillis(milliseconds);
+      return getObjectNotNull(index);
     }
   }
 
+  /**
+   * Same as {@link #getObject(int)} but does not check for null.
+   *
+   * @param index   position of element
+   * @return element at given index
+   */
+  public Duration getObjectNotNull(int index) {
+    final long startIndex = (long) index * TYPE_WIDTH;
+    final int days = valueBuffer.getInt(startIndex);
+    final int milliseconds = valueBuffer.getInt(startIndex + 
MILLISECOND_OFFSET);
+    return Duration.ofDays(days).plusMillis(milliseconds);
+  }
+
   /**
    * Get the Interval value at a given index as a {@link StringBuilder} object.
    *
diff --git 
a/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
 
b/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
index 15d6a5cf99..f9f0357861 100644
--- 
a/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
+++ 
b/java/vector/src/test/java/org/apache/arrow/vector/testing/ValueVectorDataPopulator.java
@@ -19,6 +19,7 @@ package org.apache.arrow.vector.testing;
 
 import static org.junit.Assert.assertEquals;
 
+import java.math.BigDecimal;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +30,7 @@ import org.apache.arrow.vector.BitVector;
 import org.apache.arrow.vector.BitVectorHelper;
 import org.apache.arrow.vector.DateDayVector;
 import org.apache.arrow.vector.DateMilliVector;
+import org.apache.arrow.vector.Decimal256Vector;
 import org.apache.arrow.vector.DecimalVector;
 import org.apache.arrow.vector.DurationVector;
 import org.apache.arrow.vector.FixedSizeBinaryVector;
@@ -147,6 +149,34 @@ public class ValueVectorDataPopulator {
     vector.setValueCount(length);
   }
 
+  /**
+   * Populate values for Decimal256Vector.
+   */
+  public static void setVector(Decimal256Vector vector, Long... values) {
+    final int length = values.length;
+    vector.allocateNew(length);
+    for (int i = 0; i < length; i++) {
+      if (values[i] != null) {
+        vector.set(i, values[i]);
+      }
+    }
+    vector.setValueCount(length);
+  }
+
+  /**
+   * Populate values for Decimal256Vector.
+   */
+  public static void setVector(Decimal256Vector vector, BigDecimal... values) {
+    final int length = values.length;
+    vector.allocateNew(length);
+    for (int i = 0; i < length; i++) {
+      if (values[i] != null) {
+        vector.set(i, values[i]);
+      }
+    }
+    vector.setValueCount(length);
+  }
+
   /**
    * Populate values for DurationVector.
    * @param values values of elapsed time in either seconds, milliseconds, 
microseconds or nanoseconds.


Reply via email to