import java.math.BigInteger;
import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

/**
 * Demonstrates use of the Comparable interface to sort primitive-type arrays and arrays
 * of objects.
 *
 * @author Drue Coles
 */
public class ArraySortDemo {

    public static void main(String[] args) {

        // Fill an array of doubles with 5 random numbers and sort it.
        ThreadLocalRandom rand = ThreadLocalRandom.current();
        double[] numbers = new double[5];
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = rand.nextDouble();
        }
        Arrays.sort(numbers);
        System.out.print("Sorted doubles: ");
        for (double num : numbers) {
            System.out.printf("%1.3f ", num);
        }
        System.out.println();
        
        // Sort an array of strings. This is possible because String implements the
        // Comparable interface.
        String[] animals = {"vicuna", "quokka", "okapi", "quagga", "ibex"};
        Arrays.sort(animals);
        System.out.print("Sorted Strings: ");
        for (String a : animals) {
            System.out.print(a + " ");
        }
        System.out.println();
        
        // BigInteger also implements Comparable.
        BigInteger[] bigInts = new BigInteger[5];
        for (int i = 0; i < bigInts.length; i++) {
            
            // Create a string of 10 random digits.
            String digits = "";
            for (int j = 0; j < 10; j++) {
                digits += rand.nextInt(10);
            }
            
            // Create a BigInteger using the string of random digits.
            bigInts[i] = new BigInteger(digits);
        }
        Arrays.sort(bigInts);
        System.out.println("Sorted BigIntegers:");
        for (BigInteger num : bigInts) {
            System.out.printf("   %,d %n", num);
        }
        
        // The custom class MilePace implements Comparable.
        int[][] minSec = {
            {5, 45}, {6, 1}, {7, 59}, {4, 43}, {5, 9}
        };
        MilePace[] milePaces = new MilePace[minSec.length];       
        for (int i = 0; i < 5; i++) {
            milePaces[i] = new MilePace(minSec[i][0], minSec[i][1]);
        }
        Arrays.sort(milePaces);
        System.out.print("Sorted MilePaces: ");
        for (MilePace mp : milePaces) {
            System.out.print(mp + " ");
        }      
        System.out.println();
    }
}

/**
 * Represents a runner's pace for a mile in minutes and seconds.
 */
class MilePace implements Comparable<MilePace> {

    private final int min;
    private final int sec;

    public MilePace(int min, int sec) {
        this.min = min;
        this.sec = sec;
    }

    @Override
    public String toString() {
        return String.format("%d:%02d", min, sec);
    }

    /**
     * Returns a negative integer, zero, or a positive integer depending on whether this 
     * mile pace is faster than, equal to, or slower than the other respectively.
     */
    @Override
    public int compareTo(MilePace other) {      
        if (this.min == other.min) {
            return this.sec - other.sec;
        }
        return this.min - other.min;
    }
}