public class FavoriteSorts {

    public int comparisons = 0;
    public int swaps = 0;

    public int getComparisons(){
        return this.comparisons;
    }

    public int getSwaps(){
        return this.swaps;
    }

    // bubble sort with input array
    public void bubbleSort(int[] arr) {
        for (int x = 0; x < arr.length; x++) {
            // iterate through the array to compare each element with its adjacent element
            for (int m = 0; m < arr.length - 1; m++) {
                // if the current element is greater than the adjacent element, swap them
                if (arr[m] > arr[m + 1]) {
                    int temp = arr[m];
                    arr[m] = arr[m + 1];
                    arr[m + 1] = temp;
                    swaps++; // increment swaps
                }
                comparisons++; // increment comparisons
            }
        }
    }

    // selection sort with input array
    public void selectionSort(int[] arr) {
        for (int x = 0; x < arr.length; x++) {
            // assume the current element is the smallest
            int min = x;
            // iterate through the array to find the actual smallest element
            for (int m = x + 1; m < arr.length; m++) {
                // if the current element is smaller than the assumed smallest element, update the index of the smallest element
                if (arr[m] < arr[min]) {
                    min = m;
                }
                comparisons++; // increment comparisons
            }
            // swap the current element with the smallest element
            int temp = arr[x];
            arr[x] = arr[min];
            arr[min] = temp;
            swaps++; // increment swaps
        }
    }

    // array of size 5000

    public static int[] randomArray() {
        int[] array = new int[5000];
        for (int i = 0; i < array.length; i++) {
            array[i] = (int) (Math.random());
        }
        return array;
    }


    public static void main(String[] args) {
        int[] avgTimes = new int[2];
        for (int i = 0; i < 12; i++) {
            int[] arr = randomArray();
            FavoriteSorts fs = new FavoriteSorts(); // create an instance of FavoriteSorts
            
            long startTime = System.nanoTime();
            fs.bubbleSort(arr);
            long endTime = System.nanoTime();
            long time = endTime - startTime;
            avgTimes[0] += time;
            System.out.println("~BUBBLE Sort Time: " + time + " nanoseconds");
            System.out.println("Number of Comparisons: " + fs.getComparisons());
            System.out.println("Number of Swaps: " + fs.getSwaps());
    
            arr = randomArray();
            fs = new FavoriteSorts();
            
            arr = randomArray();
            startTime = System.nanoTime();
            fs.selectionSort(arr);
            endTime = System.nanoTime();
            time = endTime - startTime;
            avgTimes[1] += time;
            System.out.println("*SELECTION Sort Time: " + time + " nanoseconds");
            System.out.println("Number of Comparisons: " + fs.getComparisons());
            System.out.println("Number of Swaps: " + fs.getSwaps());
        }
        System.out.println("!!BUBBLE Sort average time: " + avgTimes[0] / 12 + " nanoseconds");
        System.out.println("@@SELECTION sort average time : " + avgTimes[1] / 12 + " nanoseconds");
        
    } 
}

FavoriteSorts.main(null);
~BUBBLE Sort Time: 10673625 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4664625 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10507667 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4574292 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10682167 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4565917 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10549375 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4582584 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10506375 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4568167 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10597375 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4572958 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10490125 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4567125 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10597583 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4569750 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10552792 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4582125 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10619958 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4575417 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10573166 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4565833 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
~BUBBLE Sort Time: 10575250 nanoseconds
Number of Comparisons: 24995000
Number of Swaps: 0
*SELECTION Sort Time: 4801458 nanoseconds
Number of Comparisons: 12497500
Number of Swaps: 5000
!!BUBBLE Sort average time: 10577121 nanoseconds
@@SELECTION sort average time : 4599187 nanoseconds
/* This is wrapper class...
 Objective would be to push more functionality into this Class to enforce consistent definition
 */
public abstract class Collectable implements Comparable <Collectable> {
	public final String masterType = "Collectable";
	private String type;	// extender should define their data type

	// enumerated interface
	public interface KeyTypes {
		String name();
	}
	protected abstract KeyTypes getKey();  	// this method helps force usage of KeyTypes

	// getter
	public String getMasterType() {
		return masterType;
	}

	// getter
	public String getType() {
		return type;
	}

	// setter
	public void setType(String type) {
		this.type = type;
	}
	
	// this method is used to establish key order
	public abstract String toString();

	// this method is used to compare toString of objects
	public int compareTo(Collectable obj) {
		return this.toString().compareTo(obj.toString());
	}

	// static print method used by extended classes
	public static void print(Collectable[] objs) {
		// print 'Object' properties
		System.out.println(objs.getClass() + " " + objs.length);

		// print 'Collectable' properties
		if (objs.length > 0) {
			Collectable obj = objs[0];	// Look at properties of 1st element
			System.out.println(
					obj.getMasterType() + ": " + 
					obj.getType() +
					" listed by " +
					obj.getKey());
		}

		// print "Collectable: Objects'
		for(Object o : objs)	// observe that type is Opaque
			System.out.println(o);

		System.out.println();
	}
}
/*
 * People class extends Collectable and defines abstract methods
 */
public class People extends Collectable {
	// Class data
	public static KeyTypes key = KeyType.title;  // static initializer
	public static void setOrder(KeyTypes key) { People.key = key; }
	public enum KeyType implements KeyTypes {title, name, age, hairColor}

	// Instance data
	private final String name;
	private final int age;
	private final String hairColor;

	/* constructor
	 *
	 */
	public People(String name, int age, String hairColor)
	{
		super.setType("People");
		this.name = name;
		this.age = age;
		this.hairColor = hairColor;
	}

	/* 'Collectable' requires getKey to help enforce KeyTypes usage */
	@Override
	protected KeyTypes getKey() { return People.key; }

	/* Getters / Accessors
	 * 
	 */
	public String getName() { return this.name; }
	public int getAge() { return this.age; }
	public String getColor() { return this.hairColor; }

	
	/* 'Collectable' requires toString override
	 * toString provides data based off of Static Key setting
	 */
	@Override
	public String toString()
	{
		String output="";
		if (KeyType.name.equals(this.getKey())) {
			output += this.name;
		} else if (KeyType.age.equals(this.getKey())) {
			output += "00" + this.age;
			output = output.substring(output.length() - 2);
		} else if (KeyType.hairColor.equals(this.getKey())) {
			output += this.hairColor;
		} else {
			output += super.getType() + ": " + this.name + ", " + this.hairColor + ", " + this.age;
		}
		return output;
		
	}

	// Test data initializer
	public static People[] animals() {
		return new People[]{
				new People("math", 5, "Black"),
				new People("apush", 18, "Black"),
				new People("csa", 18, "Black"),
				new People("apgov", 17, "Red"),
				new People("apush", 19, "Black"),
				new People("apel", 18, "Blonde")
		};
	}
	
	/* main to test People class
	 * 
	 */
	public static void main(String[] args)
	{
		// Inheritance Hierarchy
		People[] objs = animals();

		// print with title
		People.setOrder(KeyType.title);
		People.print(objs);

		// convert to Coolection and sort in name order
		People.setOrder(KeyType.name);
		List<People> animals = new ArrayList<People>(Arrays.asList(objs));  // Array has asList conversion
		Collections.sort(animals);
		People.setOrder(KeyType.title);
		for (People people : animals)
			System.out.println(people);
	}

}
People.main(null);
class [LREPL.$JShell$79$People; 6
Collectable: People listed by title
People: Nathan, Black, 5
People: Rohit, Black, 18
People: Jun, Black, 18
People: Rose, Red, 17
People: Alvin, Black, 19
People: Vinny, Blonde, 18

People: Alvin, Black, 19
People: Jun, Black, 18
People: Nathan, Black, 5
People: Rohit, Black, 18
People: Rose, Red, 17
People: Vinny, Blonde, 18
import java.util.HashMap;

public class Students {
    // create a new HashMap
    HashMap<String, People> names = new HashMap<>();

    /* Add Students
     * 
     */
    public Students() {
        // add some key-value pairs to the HashMap
        names.put("Ritvik", new People("math", 17, "Black"));
        names.put("Alvin", new People("apush", 18, "Black"));
        names.put("Jun", new People("csa", 18, "Black"));
        names.put("Nathan", new People("apgov", 17, "Red"));
        names.put("Mark", new People("apush", 19, "Black"));
        names.put("Vinny", new People("apel", 18, "Blonde"));
    } 

    /* Remove Pet
     * 
     */
    public People remove(String key) {
        // check if a key exists in the HashMap then remove
        People people = null;
        if (names.containsKey(key)) {
            people = names.get(key);
            names.remove(key);
        }
        return people;
    }

    /* Print Students
     * 
     */
    public void print() {
        // iterate over the keys in the HashMap
        for (String name: names.keySet()) {
            People obj = names.get(name);
            System.out.println(name + " is a " + obj.getColor() + " haired " + obj.getName() + " student and is " + obj.getAge() + " years old.");
        }
        System.out.println();
    }

    /* Tester Method
     * 
     */
    public static void main(String[] args) {

        // intialize Students
        Students students = new Students();
        students.print();
        
        // remove a Pet
        String key = "Mathew";
        People people = students.remove(key);
        if (people == null) {
            System.out.println(key + " not found");
        } else {
            System.out.println("Removed: " + key + ", " + people);
        }
        students.print();

    }
}
Students.main(null);
Ritvik is a Black haired math student and is 17 years old.
Jun is a Black haired csa student and is 18 years old.
Nathan is a Red haired apgov student and is 17 years old.
Alvin is a Black haired apush student and is 18 years old.
Mark is a Black haired apush student and is 19 years old.
Vinny is a Blonde haired apel student and is 18 years old.

Mathew not found
Ritvik is a Black haired math student and is 17 years old.
Jun is a Black haired csa student and is 18 years old.
Nathan is a Red haired apgov student and is 17 years old.
Alvin is a Black haired apush student and is 18 years old.
Mark is a Black haired apush student and is 19 years old.
Vinny is a Blonde haired apel student and is 18 years old.