Skip to content

Commit

Permalink
Closes #908: Support sorting of primitive lists by indirect comparison
Browse files Browse the repository at this point in the history
Signed-off-by: vmzakharov <zakharov.vladimir.m@gmail.com>
  • Loading branch information
vmzakharov committed Jun 14, 2020
1 parent c2f479b commit 21bbc14
Show file tree
Hide file tree
Showing 7 changed files with 407 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import "copyright.stg"

targetPath() ::= "org/eclipse/collections/api/block/comparator/primitive"

fileName(primitive) ::= "<primitive.name>Comparator"

class(primitive) ::= <<
<body(primitive.type, primitive.name, primitive.wrapperName)>
>>

body(type, name, wrapperName) ::= <<
<copyright()>

package org.eclipse.collections.api.block.comparator.primitive;

import java.io.Serializable;

/**
* <name>Comparator is a primitive Comparator that takes two arguments of type <type> and
* otherwise follows the contract of {@code java.util.Comparator}.
* This comparator can be used to sort primitive collections, which support indirect sorting,
* if a sort order other thant the natural one of the collection elements is required.
*
* This file was automatically generated from template file primitiveComparator.stg.
*
*/
@FunctionalInterface
public interface <name>Comparator\<T>
extends Serializable
{
int compare(<type> value1, <type> value2);
}

>>
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,32 @@ allMethods(type) ::= <<
*/
Mutable<name>List sortThis();

/**
* Sorts the internal data structure of this list and returns the list itself as a convenience.
*/
default Mutable<name>List sortThis(<name>Comparator comparator)
{
throw new UnsupportedOperationException("sortThis(<name>Comparator comparator) is not supported on " + this.getClass());
}

/**
* Sorts the internal data structure of this list based on the natural order of the key returned by {@code
* function}.
*/
default \<T> Mutable<name>List sortThisBy(<name>ToObjectFunction\<T> function)
{
return sortThisBy(function, (Comparator\<? super T>) Comparator.naturalOrder());
}

/**
* Sorts the internal data structure of this list based on the key returned by {@code
* function} using the provided {@code comparator}.
*/
default \<T> Mutable<name>List sortThisBy(<name>ToObjectFunction\<T> function, Comparator\<? super T> comparator)
{
return this.sortThis((i1, i2) -> comparator.compare(function.valueOf(i1), function.valueOf(i2)));
}

/**
* Randomly permutes this list mutating its contents and returns the same list (this).
*
Expand Down Expand Up @@ -203,7 +229,9 @@ auxiliaryImports ::= [
]

allAuxiliaryImports(type) ::= <<
import java.util.Comparator;
import java.util.Random;
import org.eclipse.collections.api.block.comparator.primitive.<name>Comparator;

>>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import "copyright.stg"

targetPath() ::= "org/eclipse/collections/impl/utility/primitive"

fileName(primitive) ::= "<primitive.name>QuickSort"

class(primitive) ::= <<
<body(primitive.type, primitive.name, primitive.wrapperName)>
>>

body(type, name, wrapperName) ::= <<
<copyright()>

package org.eclipse.collections.impl.utility.primitive;

import org.eclipse.collections.api.block.comparator.primitive.<name>Comparator;

/**
* <name>QuickSort is an implementation of the Quick Sort algorithm as described in Donald Knuth's TAOCP with some
* optimizations. It supports indirect array sorting based on primitive comparators and/or key values extracted from
* the array values if a sort order other thant the natural one of the array elements is required.
*
* This file was automatically generated from template file primitiveSort.stg.
*
*/

public final class <name>QuickSort
{
private static final int SORT_SMALL_SIZE = 9;

private <name>QuickSort()
{
}

public static void sort(<type>[] array, int left, int right, <name>Comparator comparator)
{
int size = right - left + 1;

if (size \<= <name>QuickSort.SORT_SMALL_SIZE)
{
<name>QuickSort.insertionSort(array, left, right, comparator);
}
else
{
// Initialize new stage
int mid = (right - (right / 2)) + (left / 2);
<type> leftVal = array[left];
<type> rightVal = array[right];
<type> midVal = array[mid];

int swapIndex = -1;

if (comparator.compare(leftVal, midVal) > 0 && comparator.compare(leftVal, rightVal) > 0)
{
swapIndex = (comparator.compare(midVal, rightVal) \< 0) ? right : mid;
}
else if (comparator.compare(leftVal, midVal) \< 0 && comparator.compare(leftVal, rightVal) \< 0)
{
swapIndex = (comparator.compare(midVal, rightVal) \< 0) ? mid : right;
}

if (swapIndex > 0)
{
swap(array, left, swapIndex);
}

<type> pivot = array[left];

int i = left + 1;
int j = right;

while (i \< j)
{
// Compare: Key(i) : Key, skip all which are \<= pivot or until hit j
while (comparator.compare(array[i], pivot) \<= 0 && i \< j)
{
i++;
}

// Compare Key : Key(j), skip all which are > pivot or until hit i
while (comparator.compare(pivot, array[j]) \< 0 && j > i - 1)
{
j--;
}

if (i \< j)
{
swap(array, i, j);
}
else
{
swap(array, left, j);
}
}

// Sort partitions, skipping sequences of elements equal to the pivot
if (right > j + 1)
{
int from = j + 1;
while (right > from && comparator.compare(pivot, array[from]) == 0)
{
from++;
}
if (right > from)
{
<name>QuickSort.sort(array, from, right, comparator);
}
}

if (left \< j - 1)
{
int to = j - 1;
while (to > left && comparator.compare(pivot, array[to]) == 0)
{
to--;
}
if (left \< to)
{
<name>QuickSort.sort(array, left, to, comparator);
}
}
}
}

private static void insertionSort(<type>[] array, int left, int right, <name>Comparator comparator)
{
for (int j = left + 1; j \<= right; j++)
{
if (comparator.compare(array[j - 1], array[j]) > 0)
{
<type> key = array[j];
int i = j - 1;

do
{
array[i + 1] = array[i];
i--;
}
while (i > -1 && comparator.compare(key, array[i]) \< 0);

array[i + 1] = key;
}
}
}

private static void swap(<type>[] array, int i1, int i2)
{
<type> value = array[i1];
array[i1] = array[i2];
array[i2] = value;
}
}

>>
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import java.util.NoSuchElementException;
import org.eclipse.collections.api.<name>Iterable;
import org.eclipse.collections.api.Lazy<name>Iterable;
import org.eclipse.collections.api.RichIterable;
import org.eclipse.collections.api.block.comparator.primitive.<name>Comparator;
import org.eclipse.collections.api.block.function.primitive.Object<name>IntToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.Object<name>ToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.<name>ToObjectFunction;
Expand All @@ -53,6 +54,7 @@ import org.eclipse.collections.impl.primitive.Abstract<name>Iterable;
import org.eclipse.collections.impl.set.mutable.primitive.<name>HashSet;
import org.eclipse.collections.impl.tuple.primitive.PrimitiveTuples;
import org.eclipse.collections.impl.utility.Iterate;
import org.eclipse.collections.impl.utility.primitive.<name>QuickSort;
<if(primitive.specializedStream)>
import java.util.Spliterator;
import java.util.Spliterators;<endif>
Expand Down Expand Up @@ -1011,6 +1013,13 @@ public class <name>ArrayList extends Abstract<name>Iterable
return this;
}

@Override
public <name>ArrayList sortThis(<name>Comparator comparator)
{
<name>QuickSort.sort(this.items, 0, this.size() - 1, comparator);
return this;
}

@Override
public <name>ArrayList toReversed()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ body(type, name) ::= <<
package org.eclipse.collections.impl.list.mutable.primitive;

import java.util.Collection;
<if(!primitive.booleanPrimitive)>import java.util.Comparator;<endif>

import org.eclipse.collections.api.<name>Iterable;
import org.eclipse.collections.api.Lazy<name>Iterable;
<if(!primitive.booleanPrimitive)>import org.eclipse.collections.api.block.comparator.primitive.<name>Comparator;<endif>
import org.eclipse.collections.api.block.function.primitive.<name>IntToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.<name>ToObjectFunction;
import org.eclipse.collections.api.block.function.primitive.Object<name>IntToObjectFunction;
Expand Down Expand Up @@ -447,6 +449,36 @@ public Mutable<name>List sortThis()
return this;
}

@Override
public Mutable<name>List sortThis(<name>Comparator comparator)
{
synchronized (this.getLock())
{
this.getMutable<name>List().sortThis(comparator);
}
return this;
}

@Override
public \<T> Mutable<name>List sortThisBy(<name>ToObjectFunction\<T> function)
{
synchronized (this.getLock())
{
this.getMutable<name>List().sortThisBy(function);
}
return this;
}

@Override
public \<T> Mutable<name>List sortThisBy(<name>ToObjectFunction\<T> function, Comparator\<? super T> comparator)
{
synchronized (this.getLock())
{
this.getMutable<name>List().sortThisBy(function, comparator);
}
return this;
}

@Override
public Mutable<name>List shuffleThis()
{
Expand Down

0 comments on commit 21bbc14

Please sign in to comment.