Comparable & Comparator Interface

import java.util.*;

class Person implements Comparable<Person> {
    private static int count = 0; // static (class) field
    protected String name; // instance field
    protected int age; // instance field

    public Person() {
        //System.out.println("Person Constructor"); // this("", 0); error: call to this must be first statemenht in constructor
        this("", 0);
    }

    public Person(String name, int age) {
        count++;
        this.name = name;
        this.age = age;
    }

    public Person(Person other) {
        this(other.name, other.age);
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void set(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void set(Person other) {
        this.name = other.name;
        this.age = other.age;
    }

    public Person clone() {
        Person p = new Person(this.name, this.age);
        return p;
    }

    @Override
    public boolean equals(Object other) { // Object.equals overriding
        if (other instanceof Person) {
            Person that = (Person) other;
            return that.canEqual(this) && this.getName().equals(that.getName()) && this.getAge() == that.getAge();
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (41 * getName().hashCode() + getAge());
    }

    public boolean canEqual(Object other) {
        return (other instanceof Person);
    }

    @Override
    public String toString() { // Object.toString() overriding
        return "Person Name: " + name + " Age: " + age;
    }

    public void print() { // instance methods
        System.out.println("Person Name: " + name + " Age: " + age);
    }

    public static void printCount() { // static (class) methods
        System.out.println("Person Count: " + count);
    }

    public static int getCount() {  // static (class) methods
        return count; 
    }

    public static void setCount(int value) { // static (class) methods
        count = value; 
    } 

    public int compareTo(Person other) {
        String thisName = this.getName().toUpperCase();
        String otherName = ((Person)other).getName().toUpperCase();
        //ascending order
        return thisName.compareTo(otherName);
        //descending order
        //return otherName.compareTo(thisName);
    }

    public static Comparator<Person> AgeComparator = new Comparator<Person>() {
        public int compare(Person p1, Person p2) {
            int age1 = p1.getAge();
            int age2 = p2.getAge();
            //ascending order
            return age1 – age2;
            //descending order
            //return age2 – age1;
        }
    };
}

///////////////////////////////////////////////////////////////////////////////////////
class Student extends Person {
    private static int count = 0; // static (class) field
    protected int id;

    public Student() {
        id = 5208;
    }

    public Student(String name, int age, int id) {
        super(name, age);
        this.id = id;
        count++;
    }

    public int getID() {
        return id;
    }

    public void setID(int id) {
        this.id = id;
    }

    public void set(String name, int age, int id) {
        super.set(name, age);
        this.id = id;
    }

    public void set(String name, int age) {
        super.set(name, age);
    }

    public void set(Student other) {
        this.set(other.name, other.age, other.id);
    }

    public void set(Person other) {
        if (other instanceof Person)
            super.set(other);
        else
            this.set((Student)other);
    }

    public Student clone() {
        Student s = new Student(this.name, this.age, this.id);
        return s;
    }

    @Override
    public boolean equals(Object other) { // Object.equals overriding
        if (other instanceof Student) {
            Student that = (Student) other;
            return that.canEqual(this) && this.getName().equals(that.getName()) && this.getAge() == that.getAge() && this.getID() == that.getID();
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (41 * super.hashCode() + getID());
    }

    public boolean canEqual(Object other) {
        return (other instanceof Student);
    }

    @Override
    public String toString() { // Object.toString() overriding
        return "Student Name: " + name + " Age: " + age + " ID: " + id;
    }

    public void superPrint() {
        super.print();
    }

    public void print() { // Person.print() method overriding
        System.out.println("Student Name: " + name + " Age: " + age + " ID: " + id);
    }

    public static void printCount() { // static (class) methods
        System.out.println("Student Count: " + count);
    }

    public static int getCount() { // static (class) methods
        return count; 
    } 
    public static void setCount(int value) { // static (class) methods
        count = value; 
    }

    public int compareTo(Student other) {
        String thisName = this.getName().toUpperCase();
        String otherName = ((Student)other).getName().toUpperCase();
        //ascending order
        return thisName.compareTo(otherName);
        //descending order
        //return otherName.compareTo(thisName);
    }

    public static Comparator<Student> AgeComparator = new Comparator<Student>() {
        public int compare(Student p1, Student p2) {
            int age1 = p1.getAge();
            int age2 = p2.getAge();
            //ascending order
            return age1 – age2;
            //descending order
            //return age2 – age1;
        }
    };

    public static Comparator<Student> IDComparator = new Comparator<Student>() {
        public int compare(Student p1, Student p2) {
            int id1 = p1.getID();
            int id2 = p2.getID();
            //ascending order
            return id1 – id2;
            //descending order
            //return id2 – id1;
        }
    };
}

class PersonStudentTest {

    public static void print(Object[] array) {
        for(Object o : array) {
            System.out.println(o);
        }
    }

    public static void main(String[] args) {
///////////////////////////////////////////////////////////////////////
        Student[] sList = new Student[3];
        sList[0] = new Student("Kevin", 0, 222);
        sList[1] = new Student("Jason", 1, 333);
        sList[2] = new Student("John", 2, 111);

        System.out.println("STUDENT SORT BY NAME (DEFAULT)!!!");
        Arrays.sort(sList);
        print(sList);

        System.out.println("STUDENT SORT by AGE!!!");
        Arrays.sort(sList, Student.AgeComparator);
        print(sList);

        System.out.println("STUDENT SORT by ID!!!");
        Arrays.sort(sList, Student.IDComparator);
        print(sList);

///////////////////////////////////////////////////////////////////////
        Student[] sList2 = new Student[3];
        sList2[0] = new Student("Kevin", 0, 222);
        sList2[1] = new Student("Jason", 1, 333);
        sList2[2] = new Student("John", 2, 111);

        System.out.println("STUDENT SORT BY NAME (anonymous method)!!!");
        Arrays.sort(sList2, new Comparator<Student>() {
            public int compare(Student s1, Student s2) {
                return s1.getName().toUpperCase().compareTo(s2.getName().toUpperCase());
            }
        });
        print(sList2);

        System.out.println("STUDENT SORT by AGE (anonymous method)!!!");
        Arrays.sort(sList2, new Comparator<Student>() {
            public int compare(Student s1, Student s2) {
                return s1.getAge() – s2.getAge();
            }
        });
        print(sList2);

        System.out.println("STUDENT SORT by ID (anonymous method)!!!");
        Arrays.sort(sList2, new Comparator<Student>() {
            public int compare(Student s1, Student s2) {
                return s1.getID() – s2.getID();
            }
        });
        print(sList2);

///////////////////////////////////////////////////////////////////////
        Student[] sList3 = sList2;

        System.out.println("STUDENT SORT BY NAME (lambda)!!!");
        Arrays.sort(sList3, (Student ss1, Student ss2) ->
                            ss1.getName().compareTo(ss2.getName())
        );
        Arrays.stream(sList3).forEach((s) -> System.out.println(s));

        System.out.println("STUDENT SORT by AGE (lambda)!!!");
        Arrays.sort(sList3, (Student ss1, Student ss2) ->
                            Integer.compare(ss1.getAge(), ss2.getAge())
        );
        Arrays.stream(sList3).forEach((s) -> System.out.println(s));

        System.out.println("STUDENT SORT by ID (lambda)!!!");
        Arrays.sort(sList3, (Student ss1, Student ss2) ->
                            Integer.compare(ss1.getID(), ss2.getID())
        );
        Arrays.stream(sList3).forEach((s) -> System.out.println(s));

///////////////////////////////////////////////////////////////////////
        List<Student> sList4 = new ArrayList<Student>();
        sList4.add(new Student("Kevin", 0, 222));
        sList4.add(new Student("Jason", 1, 333));
        sList4.add(new Student("John", 2, 111));

        System.out.println("STUDENTLIST SORT BY NAME (lambda)!!!");
        sList4.sort((Student ss1, Student ss2) ->
                    ss1.getName().compareTo(ss2.getName())
        );
        sList4.forEach((s) -> System.out.println(s));

        System.out.println("STUDENTLIST SORT by AGE (lambda)!!!");
        sList4.sort((Student ss1, Student ss2) ->
                    ss1.getAge() – ss2.getAge()
        );
        sList4.forEach((s) -> System.out.println(s));

        System.out.println("STUDENTLIST SORT by ID (lambda)!!!");
        sList4.sort((Student ss1, Student ss2) ->
                    ss1.getID() – ss2.getID()
        );
        sList4.forEach((s) -> System.out.println(s));
    }

}