FileDocCategorySizeDatePackage
Sortable.javaAPI DocExample17626Wed Apr 24 12:30:02 BST 2002tuning.sorting

Sortable.java

package tuning.sorting;
import java.util.Random;
import java.util.Arrays;
import java.util.Comparator;

public class Sortable
  implements Comparable
{
  static int SEED = 1234567890;
  int order;
  public Sortable(int i){order = i;}
  public int compareTo(Object o){return order - ((Sortable) o).order;}
  public int compareToSortable(Sortable o){return order - o.order;}
  public static void main(String[] args)
  {
    maintest(args);
    if (args.length > 1)
      maintest(args);
  }

  public static void maintest(String[] args)
  {
    int SIZE = Integer.parseInt(args[0]);
    Sortable[] list = new Sortable[SIZE];
    for (int i = SIZE-1; i >= 0; i--)
      list[i] = new Sortable(i);

    long time ;
    Sortable[] listToSort;
    list = randomized(list);
    listToSort = (Sortable[]) list.clone();
    ArrayQuickSorter.SINGLETON.sort(new SortableComparer(), listToSort, 0, listToSort.length);
    quicksort_Sortable2(listToSort, 0, listToSort.length-1);
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println("here");

    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    ArrayQuickSorter.SINGLETON.sort(new SortableComparer(), listToSort, 0, listToSort.length);
    System.out.println("ArrayQuickSorter time using Sortable.method: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println(listToSort[i].order + " here " + i);

    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    ArrayQuickSorter.SINGLETON.sort(new SortableComparer2(), listToSort, 0, listToSort.length);
    System.out.println("ArrayQuickSorter time using Sortable.field: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println(listToSort[i].order + " here " + i);

    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    quicksort_Sortable2(listToSort, 0, listToSort.length-1);
    System.out.println("quicksort time using Sortable.field: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println("here");

    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    quicksort_Sortable1(listToSort, 0, listToSort.length-1);
    System.out.println("quicksort time using Sortable.method: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println("here");
    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    quicksort_Comparable(listToSort, 0, listToSort.length-1);
    System.out.println("quicksort time using Comparable: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println("here");

    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    quicksort_Object(listToSort, 0, listToSort.length-1);
    System.out.println("quicksort time using Object: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println("here");
    listToSort = (Sortable[]) list.clone();
    time = System.currentTimeMillis();
    Arrays.sort(listToSort, 0, listToSort.length);
    System.out.println("quicksort time using Arrays.sort: " + 
      (System.currentTimeMillis()-time));
    for (int i = SIZE-1; i >= 0; i--)
      if(listToSort[i].order != i)
	System.out.println("here");
  }

  public static Sortable[] randomized(Sortable[] arr)
  {
    Sortable[] list = new Sortable[arr.length];
    Sortable[] list2 = (Sortable[]) arr.clone();
    Random rand = new Random(SEED);
    int idx;
    for (int i = list.length-1; i >= 0 ; i--)
    {
	idx = (int) ((Math.abs(rand.nextInt()) * (long) i)/Integer.MAX_VALUE);
	list[i] = list2[idx];
	list2[idx] = list2[i];
	list2[i] = null;
    }
    list2 = null;
    rand = null;
    System.gc();
    return list;
  }

  public static void quicksort_Sortable1(Sortable[] arr, int lo, int hi)
  {
    if( lo >= hi ) 
      return;

    int mid = ( lo + hi ) / 2;
    Sortable tmp;
    Sortable middle = arr[ mid ];

    if( arr[ lo ].compareToSortable(middle) > 0 )
    {
      arr[ mid ] = arr[ lo ];
      arr[ lo ] = middle;
      middle = arr[ mid ];
    }
    
    if( middle.compareToSortable(arr[ hi ]) > 0)
    {
      arr[ mid ] = arr[ hi ];
      arr[ hi ] = middle;
      middle = arr[ mid ];

      if( arr[ lo ].compareToSortable(middle) > 0)
      {
        arr[ mid ] = arr[ lo ];
        arr[ lo ] = middle;
        middle = arr[ mid ];
      }
    }

    int left = lo + 1;
    int right = hi - 1;

    if( left >= right ) 
      return;

    for( ;; ) 
    {
      while( arr[ right ].compareToSortable(middle ) > 0)
      {
        right--;
      }

      while( left < right && arr[ left ].compareToSortable(middle ) <= 0)
      {
        left++;
      }

      if( left < right )
      {
        tmp = arr[ left ];
        arr[ left ] = arr[ right ];
        arr[ right ] = tmp;
        right--;
      }
      else
      {
        break;
      }
    }

    quicksort_Sortable1(arr, lo, left);
    quicksort_Sortable1(arr, left + 1, hi);
  }

  public static void quicksort_Sortable2(Sortable[] arr, int lo, int hi)
  {
    if( lo >= hi ) 
      return;

    int mid = ( lo + hi ) / 2;
    Sortable tmp;
    Sortable middle = arr[ mid ];

    if( arr[ lo ].order > middle.order )
    {
      arr[ mid ] = arr[ lo ];
      arr[ lo ] = middle;
      middle = arr[ mid ];
    }
    
    if( middle.order > arr[ hi ].order)
    {
      arr[ mid ] = arr[ hi ];
      arr[ hi ] = middle;
      middle = arr[ mid ];

      if( arr[ lo ].order > middle.order)
      {
        arr[ mid ] = arr[ lo ];
        arr[ lo ] = middle;
        middle = arr[ mid ];
      }
    }

    int left = lo + 1;
    int right = hi - 1;

    if( left >= right ) 
      return;

    for( ;; ) 
    {
      while( arr[ right ].order > middle.order)
      {
        right--;
      }

      while( left < right && arr[ left ].order <= middle.order )
      {
        left++;
      }

      if( left < right )
      {
        tmp = arr[ left ];
        arr[ left ] = arr[ right ];
        arr[ right ] = tmp;
        right--;
      }
      else
      {
        break;
      }
    }

    quicksort_Sortable2(arr, lo, left);
    quicksort_Sortable2(arr, left + 1, hi);
  }

  public static void quicksort_Comparable(Comparable[] arr, int lo, int hi)
  {
    if( lo >= hi ) 
      return;

    int mid = ( lo + hi ) / 2;
    Comparable tmp;
    Comparable middle = arr[ mid ];

    if( arr[ lo ].compareTo(middle) > 0 )
    {
      arr[ mid ] = arr[ lo ];
      arr[ lo ] = middle;
      middle = arr[ mid ];
    }
    
    if( middle.compareTo(arr[ hi ]) > 0)
    {
      arr[ mid ] = arr[ hi ];
      arr[ hi ] = middle;
      middle = arr[ mid ];

      if( arr[ lo ].compareTo(middle) > 0)
      {
        arr[ mid ] = arr[ lo ];
        arr[ lo ] = middle;
        middle = arr[ mid ];
      }
    }

    int left = lo + 1;
    int right = hi - 1;

    if( left >= right ) 
      return;

    for( ;; ) 
    {
      while( arr[ right ].compareTo(middle ) > 0)
      {
        right--;
      }

      while( left < right && arr[ left ].compareTo(middle ) <= 0)
      {
        left++;
      }

      if( left < right )
      {
        tmp = arr[ left ];
        arr[ left ] = arr[ right ];
        arr[ right ] = tmp;
        right--;
      }
      else
      {
        break;
      }
    }

    quicksort_Comparable(arr, lo, left);
    quicksort_Comparable(arr, left + 1, hi);
  }

  public static void quicksort_Object(Object[] arr, int lo, int hi)
  {
    if( lo >= hi ) 
      return;

    int mid = ( lo + hi ) / 2;
    Object tmp;
    Object middle = arr[ mid ];

    if( ((Comparable) arr[ lo ]).compareTo(middle) > 0 )
    {
      arr[ mid ] = arr[ lo ];
      arr[ lo ] = middle;
      middle = arr[ mid ];
    }
    
    if( ((Comparable) middle).compareTo(arr[ hi ]) > 0)
    {
      arr[ mid ] = arr[ hi ];
      arr[ hi ] = middle;
      middle = arr[ mid ];

      if( ((Comparable) arr[ lo ]).compareTo(middle) > 0)
      {
        arr[ mid ] = arr[ lo ];
        arr[ lo ] = middle;
        middle = arr[ mid ];
      }
    }

    int left = lo + 1;
    int right = hi - 1;

    if( left >= right ) 
      return;

    for( ;; ) 
    {
      while( ((Comparable) arr[ right ]).compareTo(middle ) > 0)
      {
        right--;
      }

      while( left < right && ((Comparable) arr[ left ]).compareTo(middle ) <= 0)
      {
        left++;
      }

      if( left < right )
      {
        tmp = arr[ left ];
        arr[ left ] = arr[ right ];
        arr[ right ] = tmp;
        right--;
      }
      else
      {
        break;
      }
    }

    quicksort_Object(arr, lo, left);
    quicksort_Object(arr, left + 1, hi);
  }

}

interface Comparer
  extends Comparator
{
  public boolean hasComparisonKeys();
  public ComparisonKey getComparisonKey(Object o);
}

interface RawIntComparer
  extends Comparer
{
  public void getComparisonKey(Object o, int[] orders, int idx);
}

class SortableComparer
 implements Comparer
{
  public boolean hasComparisonKeys(){return true;}
  public ComparisonKey getComparisonKey(Object o){
    return new IntegerComparisonKey(o, ((Sortable) o).order);}
  public int compare(Object o1, Object o2) {
    System.out.println("wrong");return 1;}
}

class SortableComparer2
 extends SortableComparer
 implements RawIntComparer
{
  public ComparisonKey getComparisonKey(Object o){
    return null;}
  public void getComparisonKey(Object s, int[] orders, int index){
    orders[index] = ((Sortable) s).order;}
}

interface ComparisonKey
{
  public int compareTo(ComparisonKey target);
  public Object getSource();
}

class IntegerComparisonKey
  implements ComparisonKey
{
  public Object source;
  public int order;
  public IntegerComparisonKey(Object source, int order) {
     this.source = source;
     this.order = order;
  }
  public int compareTo(ComparisonKey target){
    System.out.println("wrong");
    return order - ((IntegerComparisonKey) target).order;
  }
  public Object getSource() {return source;}
}

class ArrayQuickSorter
{
  public static ArrayQuickSorter SINGLETON = new ArrayQuickSorter();

  public void sort(Comparator comparator, Object[] arr, int startIndex, int length)
  {
    //If the comparator is part of the extended framework, handle
    //the special case where it recommends using comparison keys
    if (comparator instanceof Comparer && ((Comparer) comparator).hasComparisonKeys())
    {
      //wrap the objects in the ComparisonKeys
      //but if the ComparisonKey is the special case of IntegerComparisonKey,
      //handle that specially
    if (comparator instanceof RawIntComparer)
    {
      RawIntComparer comparer = (RawIntComparer) comparator;
      Object[] oarr = new Object[length];
      int[] orders = new int[length];

      for(int j = length-1, i = startIndex+length-1; j >= 0; i--, j--)
      {
          comparer.getComparisonKey(arr[i], orders, j);
          oarr[j] = arr[i];
      }

      //sort using the optimized sort for IntegerComparisonKeys
      sort_intkeys(oarr, orders, 0, length);

      //and unwrap
      for(int j = length-1, i = startIndex+length-1; j >= 0; i--, j--)
        arr[i] = oarr[j];
    }
    else
    {
      Comparer comparer = (Comparer) comparator;
      ComparisonKey first = comparer.getComparisonKey(arr[startIndex]);
      if (first instanceof IntegerComparisonKey)
      {
        //wrap in IntegerComparisonKeys
        IntegerComparisonKey[] iarr = new IntegerComparisonKey[length];
        iarr[startIndex] = (IntegerComparisonKey) first;
        for(int j = length-1, i = startIndex+length-1; j > 0; i--, j--)
          iarr[j] = (IntegerComparisonKey) comparer.getComparisonKey(arr[i]);

        //sort using the optimized sort for IntegerComparisonKeys
        sort_intkeys(iarr, 0, length);

        //and unwrap
        for(int j = length-1, i = startIndex+length-1; j >= 0; i--, j--)
          arr[i] = iarr[j].source;
      }
      else
      {
        //wrap in IntegerComparisonKeys
        ComparisonKey[] karr = new ComparisonKey[length];
        karr[startIndex] = first; 
        for(int j = length-1, i = startIndex+length-1; j > 0; i--, j--)
          karr[i] = comparer.getComparisonKey(arr[i]);

        //sort using the optimized sort for ComparisonKeys
        sort_keys(karr, 0, length);

        //and unwrap
        for(int j = length-1, i = startIndex+length-1; j >= 0; i--, j--)
          arr[i] = karr[i].getSource();
      }
    }
    }
    else
      //just use the original algorithm
      sort_comparator(comparator, arr, startIndex, length);
  }
  public void sort_comparator(Comparator comparator, Object[] arr, int startIndex, int length)
  {
    //quicksort algorithm implementation using Comparator.compare(Object, Object)
    System.out.println("wrong");
  }
  public void sort_keys(ComparisonKey[] arr, int startIndex, int length)
  {
    //quicksort algorithm implementation using ComparisonKey.compare(ComparisonKey)
    System.out.println("wrong");
  }
  public void sort_intkeys(IntegerComparisonKey[] arr, int startIndex, int length)
  {
    //quicksort algorithm implementation comparing key order directly
    //using access to the IntegerComparisonKey.order field
    //i.e if (arr[i].order > arr[j].order)
    int lo = startIndex;
    int hi = startIndex+length-1;
    quicksort_Sortable2(arr, lo, hi);
  }
  public static void quicksort_Sortable2(IntegerComparisonKey[] arr, int lo, int hi)
  {
    if( lo >= hi ) 
      return;

    int mid = ( lo + hi ) / 2;
    IntegerComparisonKey tmp;
    IntegerComparisonKey middle = arr[ mid ];

    if( arr[ lo ].order > middle.order )
    {
      arr[ mid ] = arr[ lo ];
      arr[ lo ] = middle;
      middle = arr[ mid ];
    }
    
    if( middle.order > arr[ hi ].order)
    {
      arr[ mid ] = arr[ hi ];
      arr[ hi ] = middle;
      middle = arr[ mid ];

      if( arr[ lo ].order > middle.order)
      {
        arr[ mid ] = arr[ lo ];
        arr[ lo ] = middle;
        middle = arr[ mid ];
      }
    }

    int left = lo + 1;
    int right = hi - 1;

    if( left >= right ) 
      return;

    for( ;; ) 
    {
      while( arr[ right ].order > middle.order)
      {
        right--;
      }

      while( left < right && arr[ left ].order <= middle.order )
      {
        left++;
      }

      if( left < right )
      {
        tmp = arr[ left ];
        arr[ left ] = arr[ right ];
        arr[ right ] = tmp;
        right--;
      }
      else
      {
        break;
      }
    }

    quicksort_Sortable2(arr, lo, left);
    quicksort_Sortable2(arr, left + 1, hi);
  }

  public void sort_intkeys(Object[] sources, int[] orders, int startIndex, int length)
  {
    //quicksort algorithm implementation comparing key order directly
    //using access to the IntegerComparisonKey.order field
    //i.e if (arr[i].order > arr[j].order)
    int lo = startIndex;
    int hi = startIndex+length-1;
    quicksort(sources, orders, lo, hi);
  }
  public static void quicksort(Object[] sources, int[] orders, int lo, int hi)
  {
    if( lo >= hi ) 
      return;

    int mid = ( lo + hi ) / 2;
    Object tmp_o;
    int tmp_i;
    int middle = orders[ mid ];

    if( orders[ lo ] > middle )
    {
      orders[ mid ] = orders[ lo ];
      orders[ lo ] = middle;
      middle = orders[ mid ];
      tmp_o = sources[mid];
      sources[ mid ] = sources[ lo ];
      sources[ lo ] = tmp_o;
    }
    
    if( middle > orders[ hi ])
    {
      orders[ mid ] = orders[ hi ];
      orders[ hi ] = middle;
      middle = orders[ mid ];
      tmp_o = sources[mid];
      sources[ mid ] = sources[ hi ];
      sources[ hi ] = tmp_o;

      if( orders[ lo ] > middle)
      {
        orders[ mid ] = orders[ lo ];
        orders[ lo ] = middle;
        middle = orders[ mid ];
        tmp_o = sources[mid];
        sources[ mid ] = sources[ lo ];
        sources[ lo ] = tmp_o;
      }
    }

    int left = lo + 1;
    int right = hi - 1;

    if( left >= right ) 
      return;

    for( ;; ) 
    {
      while( orders[ right ] > middle)
      {
        right--;
      }

      while( left < right && orders[ left ] <= middle )
      {
        left++;
      }

      if( left < right )
      {
        tmp_i = orders[ left ];
        orders[ left ] = orders[ right ];
        orders[ right ] = tmp_i;
        tmp_o = sources[ left ];
        sources[ left ] = sources[ right ];
        sources[ right ] = tmp_o;
        right--;
      }
      else
      {
        break;
      }
    }

    quicksort(sources, orders, lo, left);
    quicksort(sources, orders, left + 1, hi);
  }


}