Repository: jtablesaw/tablesaw
Pull request #778 (2020-03-10 12:11:39)

Sorts column data using fastutil .sort methods
Thanks for contributing.

- [x] Tick to sign-off your agreement to the [Developer Certificate of Origin (DCO) 1.1](https://developercertificate.org)

## Description
Sorts the fastutil collections using the proper `sort` method and avoids accessing the backing array via `.elements()` since it will generally have invalid data or zeros in there.

Closes issue #775

## Testing

Two tests, and everything existing still runs which is promising.



Patch:
diff --git a/core/src/main/java/tech/tablesaw/api/BooleanColumn.java b/core/src/main/java/tech/tablesaw/api/BooleanColumn.java
index 77bac183..4345df53 100644
--- a/core/src/main/java/tech/tablesaw/api/BooleanColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/BooleanColumn.java
@@ -23,8 +23,7 @@ import it.unimi.dsi.fastutil.booleans.BooleanSet;
 import it.unimi.dsi.fastutil.bytes.Byte2IntMap;
 import it.unimi.dsi.fastutil.bytes.Byte2IntOpenHashMap;
 import it.unimi.dsi.fastutil.bytes.ByteArrayList;
-import it.unimi.dsi.fastutil.bytes.ByteArrays;
-import it.unimi.dsi.fastutil.bytes.ByteComparator;
+import it.unimi.dsi.fastutil.bytes.ByteComparators;
 import it.unimi.dsi.fastutil.bytes.ByteIterator;
 import it.unimi.dsi.fastutil.bytes.ByteListIterator;
 import it.unimi.dsi.fastutil.bytes.ByteOpenHashSet;
@@ -59,8 +58,6 @@ public class BooleanColumn extends AbstractColumn<BooleanColumn, Boolean>
         BooleanFillers<BooleanColumn>,
         BooleanFilters {
 
-  private final ByteComparator descendingByteComparator = (o1, o2) -> Byte.compare(o2, o1);
-
   private ByteArrayList data;
 
   private final IntComparator comparator =
@@ -297,12 +294,12 @@ public class BooleanColumn extends AbstractColumn<BooleanColumn, Boolean>
 
   @Override
   public void sortAscending() {
-    ByteArrays.mergeSort(data.elements());
+    data.sort(ByteComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    ByteArrays.mergeSort(data.elements(), descendingByteComparator);
+    data.sort(ByteComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
diff --git a/core/src/main/java/tech/tablesaw/api/DateColumn.java b/core/src/main/java/tech/tablesaw/api/DateColumn.java
index d30dff15..41915204 100644
--- a/core/src/main/java/tech/tablesaw/api/DateColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/DateColumn.java
@@ -18,6 +18,7 @@ import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.ints.IntArrayList;
 import it.unimi.dsi.fastutil.ints.IntArrays;
 import it.unimi.dsi.fastutil.ints.IntComparator;
+import it.unimi.dsi.fastutil.ints.IntComparators;
 import it.unimi.dsi.fastutil.ints.IntIterator;
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
@@ -25,7 +26,6 @@ import java.nio.ByteBuffer;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -44,7 +44,6 @@ import tech.tablesaw.columns.dates.DateFilters;
 import tech.tablesaw.columns.dates.DateMapFunctions;
 import tech.tablesaw.columns.dates.PackedLocalDate;
 import tech.tablesaw.selection.Selection;
-import tech.tablesaw.sorting.comparators.DescendingIntComparator;
 
 /** A column in a base table that contains float values */
 public class DateColumn extends AbstractColumn<DateColumn, LocalDate>
@@ -53,8 +52,6 @@ public class DateColumn extends AbstractColumn<DateColumn, LocalDate>
         DateMapFunctions,
         CategoricalColumn<LocalDate> {
 
-  private final IntComparator reverseIntComparator = DescendingIntComparator.instance();
-
   private IntArrayList data;
 
   private final IntComparator comparator =
@@ -210,12 +207,12 @@ public class DateColumn extends AbstractColumn<DateColumn, LocalDate>
 
   @Override
   public void sortAscending() {
-    Arrays.parallelSort(data.elements());
+    data.sort(IntComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    IntArrays.parallelQuickSort(data.elements(), reverseIntComparator);
+    data.sort(IntComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
@@ -437,7 +434,7 @@ public class DateColumn extends AbstractColumn<DateColumn, LocalDate>
   public List<LocalDate> top(int n) {
     List<LocalDate> top = new ArrayList<>();
     int[] values = data.toIntArray();
-    IntArrays.parallelQuickSort(values, DescendingIntComparator.instance());
+    IntArrays.parallelQuickSort(values, IntComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(PackedLocalDate.asLocalDate(values[i]));
     }
diff --git a/core/src/main/java/tech/tablesaw/api/DateTimeColumn.java b/core/src/main/java/tech/tablesaw/api/DateTimeColumn.java
index 8a38ffaa..4bd25935 100644
--- a/core/src/main/java/tech/tablesaw/api/DateTimeColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/DateTimeColumn.java
@@ -18,7 +18,7 @@ import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.ints.IntComparator;
 import it.unimi.dsi.fastutil.longs.LongArrayList;
 import it.unimi.dsi.fastutil.longs.LongArrays;
-import it.unimi.dsi.fastutil.longs.LongComparator;
+import it.unimi.dsi.fastutil.longs.LongComparators;
 import it.unimi.dsi.fastutil.longs.LongIterator;
 import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
 import it.unimi.dsi.fastutil.longs.LongSet;
@@ -31,7 +31,6 @@ import java.time.ZoneOffset;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -50,7 +49,6 @@ import tech.tablesaw.columns.datetimes.DateTimeMapFunctions;
 import tech.tablesaw.columns.datetimes.PackedLocalDateTime;
 import tech.tablesaw.columns.temporal.TemporalFillers;
 import tech.tablesaw.selection.Selection;
-import tech.tablesaw.sorting.comparators.DescendingLongComparator;
 
 /** A column in a table that contains long-integer encoded (packed) local date-time values */
 public class DateTimeColumn extends AbstractColumn<DateTimeColumn, LocalDateTime>
@@ -59,8 +57,6 @@ public class DateTimeColumn extends AbstractColumn<DateTimeColumn, LocalDateTime
         TemporalFillers<LocalDateTime, DateTimeColumn>,
         CategoricalColumn<LocalDateTime> {
 
-  private final LongComparator reverseLongComparator = DescendingLongComparator.instance();
-
   private LongArrayList data;
 
   private final IntComparator comparator =
@@ -293,12 +289,12 @@ public class DateTimeColumn extends AbstractColumn<DateTimeColumn, LocalDateTime
 
   @Override
   public void sortAscending() {
-    Arrays.parallelSort(data.elements());
+    data.sort(LongComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    LongArrays.parallelQuickSort(data.elements(), reverseLongComparator);
+    data.sort(LongComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
@@ -559,7 +555,7 @@ public class DateTimeColumn extends AbstractColumn<DateTimeColumn, LocalDateTime
   public List<LocalDateTime> top(int n) {
     List<LocalDateTime> top = new ArrayList<>();
     long[] values = data.toLongArray();
-    LongArrays.parallelQuickSort(values, DescendingLongComparator.instance());
+    LongArrays.parallelQuickSort(values, LongComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(PackedLocalDateTime.asLocalDateTime(values[i]));
     }
diff --git a/core/src/main/java/tech/tablesaw/api/DoubleColumn.java b/core/src/main/java/tech/tablesaw/api/DoubleColumn.java
index 075b6277..21a534ee 100644
--- a/core/src/main/java/tech/tablesaw/api/DoubleColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/DoubleColumn.java
@@ -3,7 +3,7 @@ package tech.tablesaw.api;
 import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
 import it.unimi.dsi.fastutil.doubles.DoubleArrays;
-import it.unimi.dsi.fastutil.doubles.DoubleComparator;
+import it.unimi.dsi.fastutil.doubles.DoubleComparators;
 import it.unimi.dsi.fastutil.doubles.DoubleIterator;
 import it.unimi.dsi.fastutil.doubles.DoubleListIterator;
 import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
@@ -28,11 +28,6 @@ import tech.tablesaw.selection.Selection;
 public class DoubleColumn extends NumberColumn<DoubleColumn, Double>
     implements NumberFillers<DoubleColumn> {
 
-  /**
-   * Compares two doubles, such that a sort based on this comparator would sort in descending order
-   */
-  private final DoubleComparator descendingComparator = (o2, o1) -> (Double.compare(o1, o2));
-
   private final DoubleArrayList data;
 
   protected DoubleColumn(String name, DoubleArrayList data) {
@@ -182,7 +177,7 @@ public class DoubleColumn extends NumberColumn<DoubleColumn, Double>
   public DoubleColumn top(int n) {
     DoubleArrayList top = new DoubleArrayList();
     double[] values = data.toDoubleArray();
-    DoubleArrays.parallelQuickSort(values, descendingComparator);
+    DoubleArrays.parallelQuickSort(values, DoubleComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(values[i]);
     }
@@ -397,12 +392,12 @@ public class DoubleColumn extends NumberColumn<DoubleColumn, Double>
 
   @Override
   public void sortAscending() {
-    DoubleArrays.parallelQuickSort(data.elements());
+    data.sort(DoubleComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    DoubleArrays.parallelQuickSort(data.elements(), descendingComparator);
+    data.sort(DoubleComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
diff --git a/core/src/main/java/tech/tablesaw/api/FloatColumn.java b/core/src/main/java/tech/tablesaw/api/FloatColumn.java
index dd28e828..58611996 100644
--- a/core/src/main/java/tech/tablesaw/api/FloatColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/FloatColumn.java
@@ -3,7 +3,7 @@ package tech.tablesaw.api;
 import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.floats.FloatArrayList;
 import it.unimi.dsi.fastutil.floats.FloatArrays;
-import it.unimi.dsi.fastutil.floats.FloatComparator;
+import it.unimi.dsi.fastutil.floats.FloatComparators;
 import it.unimi.dsi.fastutil.floats.FloatListIterator;
 import it.unimi.dsi.fastutil.floats.FloatOpenHashSet;
 import it.unimi.dsi.fastutil.floats.FloatSet;
@@ -17,11 +17,6 @@ import tech.tablesaw.columns.numbers.NumberColumnFormatter;
 
 public class FloatColumn extends NumberColumn<FloatColumn, Float> {
 
-  /**
-   * Compares two doubles, such that a sort based on this comparator would sort in descending order
-   */
-  private final FloatComparator descendingComparator = (o2, o1) -> (Float.compare(o1, o2));
-
   private final FloatArrayList data;
 
   private FloatColumn(String name, FloatArrayList data) {
@@ -125,7 +120,7 @@ public class FloatColumn extends NumberColumn<FloatColumn, Float> {
   public FloatColumn top(int n) {
     FloatArrayList top = new FloatArrayList();
     float[] values = data.toFloatArray();
-    FloatArrays.parallelQuickSort(values, descendingComparator);
+    FloatArrays.parallelQuickSort(values, FloatComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(values[i]);
     }
@@ -305,12 +300,12 @@ public class FloatColumn extends NumberColumn<FloatColumn, Float> {
 
   @Override
   public void sortAscending() {
-    FloatArrays.parallelQuickSort(data.elements());
+    data.sort(FloatComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    FloatArrays.parallelQuickSort(data.elements(), descendingComparator);
+    data.sort(FloatComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
diff --git a/core/src/main/java/tech/tablesaw/api/InstantColumn.java b/core/src/main/java/tech/tablesaw/api/InstantColumn.java
index af20d3ff..164c5a15 100644
--- a/core/src/main/java/tech/tablesaw/api/InstantColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/InstantColumn.java
@@ -21,7 +21,7 @@ import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.ints.IntComparator;
 import it.unimi.dsi.fastutil.longs.LongArrayList;
 import it.unimi.dsi.fastutil.longs.LongArrays;
-import it.unimi.dsi.fastutil.longs.LongComparator;
+import it.unimi.dsi.fastutil.longs.LongComparators;
 import it.unimi.dsi.fastutil.longs.LongIterator;
 import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
 import it.unimi.dsi.fastutil.longs.LongSet;
@@ -33,7 +33,6 @@ import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -52,7 +51,6 @@ import tech.tablesaw.columns.instant.PackedInstant;
 import tech.tablesaw.columns.temporal.TemporalFillers;
 import tech.tablesaw.columns.temporal.TemporalFilters;
 import tech.tablesaw.selection.Selection;
-import tech.tablesaw.sorting.comparators.DescendingLongComparator;
 
 /** A column in a table that contains long-integer encoded (packed) local date-time values */
 public class InstantColumn extends AbstractColumn<InstantColumn, Instant>
@@ -61,8 +59,6 @@ public class InstantColumn extends AbstractColumn<InstantColumn, Instant>
         TemporalFilters<Instant>,
         CategoricalColumn<Instant> {
 
-  private final LongComparator reverseLongComparator = DescendingLongComparator.instance();
-
   private LongArrayList data;
 
   private final IntComparator comparator =
@@ -283,12 +279,12 @@ public class InstantColumn extends AbstractColumn<InstantColumn, Instant>
 
   @Override
   public void sortAscending() {
-    Arrays.parallelSort(data.elements());
+    data.sort(LongComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    LongArrays.parallelQuickSort(data.elements(), reverseLongComparator);
+    data.sort(LongComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
@@ -546,7 +542,7 @@ public class InstantColumn extends AbstractColumn<InstantColumn, Instant>
   public List<Instant> top(int n) {
     List<Instant> top = new ArrayList<>();
     long[] values = data.toLongArray();
-    LongArrays.parallelQuickSort(values, DescendingLongComparator.instance());
+    LongArrays.parallelQuickSort(values, LongComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(PackedInstant.asInstant(values[i]));
     }
diff --git a/core/src/main/java/tech/tablesaw/api/IntColumn.java b/core/src/main/java/tech/tablesaw/api/IntColumn.java
index 145399f0..94939f95 100644
--- a/core/src/main/java/tech/tablesaw/api/IntColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/IntColumn.java
@@ -3,7 +3,7 @@ package tech.tablesaw.api;
 import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.ints.IntArrayList;
 import it.unimi.dsi.fastutil.ints.IntArrays;
-import it.unimi.dsi.fastutil.ints.IntComparator;
+import it.unimi.dsi.fastutil.ints.IntComparators;
 import it.unimi.dsi.fastutil.ints.IntListIterator;
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
@@ -19,9 +19,6 @@ import tech.tablesaw.columns.numbers.NumberColumnFormatter;
 public class IntColumn extends NumberColumn<IntColumn, Integer>
     implements CategoricalColumn<Integer> {
 
-  /** Compares two ints, such that a sort based on this comparator would sort in descending order */
-  private final IntComparator descendingComparator = (o2, o1) -> (Integer.compare(o1, o2));
-
   private final IntArrayList data;
 
   protected IntColumn(final String name, IntArrayList data) {
@@ -131,7 +128,7 @@ public class IntColumn extends NumberColumn<IntColumn, Integer>
   public IntColumn top(int n) {
     final IntArrayList top = new IntArrayList();
     final int[] values = data.toIntArray();
-    IntArrays.parallelQuickSort(values, descendingComparator);
+    IntArrays.parallelQuickSort(values, IntComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(values[i]);
     }
@@ -333,12 +330,12 @@ public class IntColumn extends NumberColumn<IntColumn, Integer>
 
   @Override
   public void sortAscending() {
-    IntArrays.parallelQuickSort(data.elements());
+    data.sort(IntComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    IntArrays.parallelQuickSort(data.elements(), descendingComparator);
+    data.sort(IntComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
diff --git a/core/src/main/java/tech/tablesaw/api/LongColumn.java b/core/src/main/java/tech/tablesaw/api/LongColumn.java
index a9ad34e7..0a81b550 100644
--- a/core/src/main/java/tech/tablesaw/api/LongColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/LongColumn.java
@@ -3,7 +3,7 @@ package tech.tablesaw.api;
 import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.longs.LongArrayList;
 import it.unimi.dsi.fastutil.longs.LongArrays;
-import it.unimi.dsi.fastutil.longs.LongComparator;
+import it.unimi.dsi.fastutil.longs.LongComparators;
 import it.unimi.dsi.fastutil.longs.LongListIterator;
 import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
 import it.unimi.dsi.fastutil.longs.LongSet;
@@ -20,9 +20,6 @@ import tech.tablesaw.columns.numbers.NumberColumnFormatter;
 
 public class LongColumn extends NumberColumn<LongColumn, Long> implements CategoricalColumn<Long> {
 
-  /** Compares two ints, such that a sort based on this comparator would sort in descending order */
-  private final LongComparator descendingComparator = (o2, o1) -> (Long.compare(o1, o2));
-
   private final LongArrayList data;
 
   private LongColumn(String name, LongArrayList data) {
@@ -133,7 +130,7 @@ public class LongColumn extends NumberColumn<LongColumn, Long> implements Catego
   public LongColumn top(int n) {
     final LongArrayList top = new LongArrayList();
     final long[] values = data.toLongArray();
-    LongArrays.parallelQuickSort(values, descendingComparator);
+    LongArrays.parallelQuickSort(values, LongComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(values[i]);
     }
@@ -360,12 +357,12 @@ public class LongColumn extends NumberColumn<LongColumn, Long> implements Catego
 
   @Override
   public void sortAscending() {
-    LongArrays.parallelQuickSort(data.elements());
+    data.sort(LongComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    LongArrays.parallelQuickSort(data.elements(), descendingComparator);
+    data.sort(LongComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
diff --git a/core/src/main/java/tech/tablesaw/api/ShortColumn.java b/core/src/main/java/tech/tablesaw/api/ShortColumn.java
index 1bc9a317..4e7a6136 100644
--- a/core/src/main/java/tech/tablesaw/api/ShortColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/ShortColumn.java
@@ -4,7 +4,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.primitives.Shorts;
 import it.unimi.dsi.fastutil.shorts.ShortArrayList;
 import it.unimi.dsi.fastutil.shorts.ShortArrays;
-import it.unimi.dsi.fastutil.shorts.ShortComparator;
+import it.unimi.dsi.fastutil.shorts.ShortComparators;
 import it.unimi.dsi.fastutil.shorts.ShortListIterator;
 import it.unimi.dsi.fastutil.shorts.ShortOpenHashSet;
 import it.unimi.dsi.fastutil.shorts.ShortSet;
@@ -21,9 +21,6 @@ import tech.tablesaw.columns.numbers.ShortColumnType;
 public class ShortColumn extends NumberColumn<ShortColumn, Short>
     implements CategoricalColumn<Short> {
 
-  /** Compares two ints, such that a sort based on this comparator would sort in descending order */
-  private final ShortComparator descendingComparator = (o2, o1) -> (Short.compare(o1, o2));
-
   private final ShortArrayList data;
 
   protected ShortColumn(final String name, ShortArrayList data) {
@@ -119,7 +116,7 @@ public class ShortColumn extends NumberColumn<ShortColumn, Short>
   public ShortColumn top(int n) {
     final ShortArrayList top = new ShortArrayList();
     final short[] values = data.toShortArray();
-    ShortArrays.parallelQuickSort(values, descendingComparator);
+    ShortArrays.parallelQuickSort(values, ShortComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(values[i]);
     }
@@ -337,12 +334,12 @@ public class ShortColumn extends NumberColumn<ShortColumn, Short>
 
   @Override
   public void sortAscending() {
-    ShortArrays.parallelQuickSort(data.elements());
+    data.sort(ShortComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    ShortArrays.parallelQuickSort(data.elements(), descendingComparator);
+    data.sort(ShortComparators.OPPOSITE_COMPARATOR);
   }
 
   @Override
diff --git a/core/src/main/java/tech/tablesaw/api/TimeColumn.java b/core/src/main/java/tech/tablesaw/api/TimeColumn.java
index 6ada50de..24778ab0 100644
--- a/core/src/main/java/tech/tablesaw/api/TimeColumn.java
+++ b/core/src/main/java/tech/tablesaw/api/TimeColumn.java
@@ -21,6 +21,7 @@ import com.google.common.base.Preconditions;
 import it.unimi.dsi.fastutil.ints.IntArrayList;
 import it.unimi.dsi.fastutil.ints.IntArrays;
 import it.unimi.dsi.fastutil.ints.IntComparator;
+import it.unimi.dsi.fastutil.ints.IntComparators;
 import it.unimi.dsi.fastutil.ints.IntIterator;
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
@@ -28,7 +29,6 @@ import java.nio.ByteBuffer;
 import java.time.LocalTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
@@ -45,7 +45,6 @@ import tech.tablesaw.columns.times.TimeFillers;
 import tech.tablesaw.columns.times.TimeFilters;
 import tech.tablesaw.columns.times.TimeMapFunctions;
 import tech.tablesaw.selection.Selection;
-import tech.tablesaw.sorting.comparators.DescendingIntComparator;
 
 /** A column in a base table that contains float values */
 public class TimeColumn extends AbstractColumn<TimeColumn, LocalTime>
@@ -54,8 +53,6 @@ public class TimeColumn extends AbstractColumn<TimeColumn, LocalTime>
         TimeFillers<TimeColumn>,
         TimeMapFunctions {
 
-  private final IntComparator descendingIntComparator = DescendingIntComparator.instance();
-
   private TimeColumnFormatter printFormatter = new TimeColumnFormatter();
 
   private IntArrayList data;
@@ -258,14 +255,12 @@ public class TimeColumn extends AbstractColumn<TimeColumn, LocalTime>
 
   @Override
   public void sortAscending() {
-    int[] sorted = data.toIntArray();
-    Arrays.parallelSort(sorted);
-    this.data = new IntArrayList(sorted);
+    data.sort(IntComparators.NATURAL_COMPARATOR);
   }
 
   @Override
   public void sortDescending() {
-    IntArrays.parallelQuickSort(data.elements(), descendingIntComparator);
+    data.sort(IntComparators.OPPOSITE_COMPARATOR);
   }
 
   public LocalTime max() {
@@ -443,7 +438,7 @@ public class TimeColumn extends AbstractColumn<TimeColumn, LocalTime>
   public List<LocalTime> top(int n) {
     List<LocalTime> top = new ArrayList<>();
     int[] values = data.toIntArray();
-    IntArrays.parallelQuickSort(values, descendingIntComparator);
+    IntArrays.parallelQuickSort(values, IntComparators.OPPOSITE_COMPARATOR);
     for (int i = 0; i < n && i < values.length; i++) {
       top.add(PackedLocalTime.asLocalTime(values[i]));
     }
diff --git a/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingIntComparator.java b/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingIntComparator.java
index 7fb90317..31a53480 100644
--- a/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingIntComparator.java
+++ b/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingIntComparator.java
@@ -15,15 +15,14 @@
 package tech.tablesaw.sorting.comparators;
 
 import it.unimi.dsi.fastutil.ints.IntComparator;
+import it.unimi.dsi.fastutil.ints.IntComparators;
 import javax.annotation.concurrent.Immutable;
 
 /** A Comparator for sorting int primitives in descending order */
 @Immutable
 public final class DescendingIntComparator {
 
-  private static final IntComparator reverseIntComparator = (o2, o1) -> (Integer.compare(o1, o2));
-
   public static IntComparator instance() {
-    return reverseIntComparator;
+    return IntComparators.OPPOSITE_COMPARATOR;
   }
 }
diff --git a/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingLongComparator.java b/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingLongComparator.java
index 163d6cb7..48a1b242 100644
--- a/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingLongComparator.java
+++ b/core/src/main/java/tech/tablesaw/sorting/comparators/DescendingLongComparator.java
@@ -15,15 +15,14 @@
 package tech.tablesaw.sorting.comparators;
 
 import it.unimi.dsi.fastutil.longs.LongComparator;
+import it.unimi.dsi.fastutil.longs.LongComparators;
 import javax.annotation.concurrent.Immutable;
 
 /** A comparator for long primitives for sorting in descending order */
 @Immutable
 public final class DescendingLongComparator {
 
-  private static final LongComparator reverseLongComparator = (o2, o1) -> (Long.compare(o1, o2));
-
   public static LongComparator instance() {
-    return reverseLongComparator;
+    return LongComparators.OPPOSITE_COMPARATOR;
   }
 }
diff --git a/core/src/main/java/tech/tablesaw/table/Relation.java b/core/src/main/java/tech/tablesaw/table/Relation.java
index 5f174ecc..a8ca304f 100644
--- a/core/src/main/java/tech/tablesaw/table/Relation.java
+++ b/core/src/main/java/tech/tablesaw/table/Relation.java
@@ -15,6 +15,7 @@
 package tech.tablesaw.table;
 
 import it.unimi.dsi.fastutil.ints.IntArrays;
+import it.unimi.dsi.fastutil.ints.IntComparators;
 import java.io.ByteArrayOutputStream;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,7 +42,6 @@ import tech.tablesaw.columns.Column;
 import tech.tablesaw.conversion.TableConverter;
 import tech.tablesaw.conversion.smile.SmileConverter;
 import tech.tablesaw.io.string.DataFramePrinter;
-import tech.tablesaw.sorting.comparators.DescendingIntComparator;
 
 /**
  * A tabular data structure like a table in a relational database, but not formally implementing the
@@ -62,7 +62,7 @@ public abstract class Relation implements Iterable<Row> {
   }
 
   public Relation removeColumns(int... columnIndexes) {
-    IntArrays.quickSort(columnIndexes, DescendingIntComparator.instance());
+    IntArrays.quickSort(columnIndexes, IntComparators.OPPOSITE_COMPARATOR);
     for (int i : columnIndexes) {
       removeColumns(column(i));
     }
diff --git a/jsplot/src/main/java/tech/tablesaw/plotly/components/Domain.java b/jsplot/src/main/java/tech/tablesaw/plotly/components/Domain.java
new file mode 100644
index 00000000..83e0aa6e
--- /dev/null
+++ b/jsplot/src/main/java/tech/tablesaw/plotly/components/Domain.java
@@ -0,0 +1,75 @@
+package tech.tablesaw.plotly.components;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Domain extends Component {
+
+  private final Integer row;
+  private final Integer column;
+  private final double[] x;
+  private final double[] y;
+
+  private Domain(DomainBuilder builder) {
+    this.x = builder.x;
+    this.y = builder.y;
+    this.row = builder.row;
+    this.column = builder.column;
+  }
+
+  @Override
+  public String asJavascript() {
+    return asJSON();
+  }
+
+  @Override
+  protected Map<String, Object> getContext() {
+    Map<String, Object> context = new HashMap<>();
+    context.put("column", column);
+    context.put("row", row);
+    context.put("x", x);
+    context.put("y", y);
+    return context;
+  }
+
+  @Override
+  protected Map<String, Object> getJSONContext() {
+    return getContext();
+  }
+
+  public static DomainBuilder builder() {
+    return new DomainBuilder();
+  }
+
+  public static class DomainBuilder {
+
+    private Integer row;
+    private Integer column;
+    private double[] x;
+    private double[] y;
+
+    public DomainBuilder row(int row) {
+      this.row = row;
+      return this;
+    }
+
+    public DomainBuilder column(int column) {
+      this.column = column;
+      return this;
+    }
+
+    public DomainBuilder x(double[] x) {
+      this.x = x;
+      return this;
+    }
+
+    public DomainBuilder y(double[] y) {
+      this.y = y;
+      return this;
+    }
+
+    public Domain build() {
+      return new Domain(this);
+    }
+  }
+}
diff --git a/jsplot/src/main/java/tech/tablesaw/plotly/traces/PieTrace.java b/jsplot/src/main/java/tech/tablesaw/plotly/traces/PieTrace.java
index a47a70de..02af6ad2 100644
--- a/jsplot/src/main/java/tech/tablesaw/plotly/traces/PieTrace.java
+++ b/jsplot/src/main/java/tech/tablesaw/plotly/traces/PieTrace.java
@@ -10,16 +10,19 @@ import java.util.Map;
 import tech.tablesaw.api.NumericColumn;
 import tech.tablesaw.columns.Column;
 import tech.tablesaw.plotly.Utils;
+import tech.tablesaw.plotly.components.Domain;
 
 public class PieTrace extends AbstractTrace {
 
   private final double[] values;
   private final Object[] labels;
+  private final Domain domain;
 
   private PieTrace(PieBuilder builder) {
     super(builder);
     this.values = builder.values;
     this.labels = builder.labels;
+    this.domain = builder.domain;
   }
 
   @Override
@@ -46,6 +49,9 @@ public class PieTrace extends AbstractTrace {
     if (labels != null) {
       context.put("labels", Utils.dataAsString(labels));
     }
+    if (domain != null) {
+      context.put("domain", domain.asJavascript());
+    }
     return context;
   }
 
@@ -62,12 +68,18 @@ public class PieTrace extends AbstractTrace {
     private final String type = "pie";
     private final double[] values;
     private final Object[] labels;
+    private Domain domain;
 
     private PieBuilder(Object[] labels, double[] values) {
       this.labels = labels;
       this.values = values;
     }
 
+    public PieBuilder domain(Domain domain) {
+      this.domain = domain;
+      return this;
+    }
+
     public PieTrace build() {
       return new PieTrace(this);
     }
diff --git a/jsplot/src/main/resources/pie_trace_template.html b/jsplot/src/main/resources/pie_trace_template.html
index d6c576d8..ed8f4c04 100644
--- a/jsplot/src/main/resources/pie_trace_template.html
+++ b/jsplot/src/main/resources/pie_trace_template.html
@@ -5,6 +5,9 @@ var {{variableName}} =
 {% endif %}
 {% if values is not null %}
         values: {{values | raw}},
+{% endif %}
+{% if domain is not null %}
+        domain: {{domain | raw}},
 {% endif %}
         type: '{{type}}',
         name: '{{name}}',


Test patch:
diff --git a/core/src/test/java/tech/tablesaw/api/DoubleColumnTest.java b/core/src/test/java/tech/tablesaw/api/DoubleColumnTest.java
index 329647cb..38a74bef 100644
--- a/core/src/test/java/tech/tablesaw/api/DoubleColumnTest.java
+++ b/core/src/test/java/tech/tablesaw/api/DoubleColumnTest.java
@@ -17,7 +17,6 @@ package tech.tablesaw.api;
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 
 import java.util.Arrays;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 
 public class DoubleColumnTest {
@@ -30,6 +29,14 @@ public class DoubleColumnTest {
     assertArrayEquals(arr, new double[] {1.0, 2.0, 3.0, 4.0, 5.0});
   }
 
+  @Test
+  public void createThenSortAscending() {
+    DoubleColumn col = DoubleColumn.create("test");
+    col.append(3.0).append(1.0).append(2.0).append(4.0);
+    col.sortAscending();
+    assertArrayEquals(new double[] {1.0, 2.0, 3.0, 4.0}, col.asDoubleArray());
+  }
+
   @Test
   public void sortAscending() {
     DoubleColumn col = DoubleColumn.create("test", 3.0, 1.0, 2.0, 4.0);
@@ -38,7 +45,6 @@ public class DoubleColumnTest {
   }
 
   @Test
-  @Disabled
   public void uniqueThenSort() {
     DoubleColumn uniq = DoubleColumn.create("test", 5, 4, 3, 2, 1, 5, 4, 3, 2, 1).unique();
     uniq.sortAscending();