/* 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();
	}
}
/*
 * Animal class extends Collectable and defines abstract methods
 */
public class Animal extends Collectable {
	// Class data
	public static KeyTypes key = KeyType.title;  // static initializer
	public static void setOrder(KeyTypes key) { Animal.key = key; }
	public enum KeyType implements KeyTypes {title, name, age, color}

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

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

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

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

	
	/* '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.color.equals(this.getKey())) {
			output += this.color;
		} else {
			output += super.getType() + ": " + this.name + ", " + this.color + ", " + this.age;
		}
		return output;
		
	}

	// Test data initializer
	public static Animal[] animals() {
		return new Animal[]{
				new Animal("Lion", 8, "Gold"),
				new Animal("Pig", 3, "Pink"),
				new Animal("Robin", 7, "Red"),
				new Animal("Cat", 10, "Black"),
				new Animal("Kitty", 1, "Calico"),
				new Animal("Dog", 14, "Brown")
		};
	}
	
	/* main to test Animal class
	 * 
	 */
	public static void main(String[] args)
	{
		// Inheritance Hierarchy
		Animal[] objs = animals();

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

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

}
Animal.main(null);
class [LREPL.$JShell$12$Animal; 6
Collectable: Animal listed by title
Animal: Lion, Gold, 8
Animal: Pig, Pink, 3
Animal: Robin, Red, 7
Animal: Cat, Black, 10
Animal: Kitty, Calico, 1
Animal: Dog, Brown, 14

Animal: Cat, Black, 10
Animal: Dog, Brown, 14
Animal: Kitty, Calico, 1
Animal: Lion, Gold, 8
Animal: Pig, Pink, 3
Animal: Robin, Red, 7
import java.util.HashMap;

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

    /* Add Pets
     * 
     */
    public Pets() {
        // add some key-value pairs to the HashMap
        names.put("Leo", new Animal("Lion", 8, "Gold"));
        names.put("Porky", new Animal("Pig", 3, "Pink"));
        names.put("Ro-Ro", new Animal("Robin", 7, "Red"));
        names.put("Midnight", new Animal("Cat", 10, "Black"));
        names.put("Hobbes", new Animal("Kitty", 1, "Calico"));
        names.put("Duke", new Animal("Dog", 14, "Brown"));
    } 

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

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

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

        // intialize Pets
        Pets pets = new Pets();
        pets.print();
        
        // remove Pet
        /* 
        Animal animal = pets.remove("Hobbes");
        if (animal == null) {
            System.out.println(key + " not found");
        } else {
            System.out.println("Removed: " + key + ", " + animal);
        }
        pets.print();
        */

    }
}
Pets.main(null);
Hobbes is a Calico Kitty and is 1 years old.
Leo is a Gold Lion and is 8 years old.
Porky is a Pink Pig and is 3 years old.
Ro-Ro is a Red Robin and is 7 years old.
Duke is a Brown Dog and is 14 years old.
Midnight is a Black Cat and is 10 years old.

import java.util.HashMap;

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

    /* Add Pets
     * 
     */
    public Pets() {
        // add some key-value pairs to the HashMap
        names.put("Leo", new Animal("Lion", 8, "Gold"));
        names.put("Porky", new Animal("Pig", 3, "Pink"));
        names.put("Ro-Ro", new Animal("Robin", 7, "Red"));
        names.put("Midnight", new Animal("Cat", 10, "Black"));
        names.put("Hobbes", new Animal("Kitty", 1, "Calico"));
        names.put("Duke", new Animal("Dog", 14, "Brown"));
    } 

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

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

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

        // intialize Pets
        Pets pets = new Pets();
        pets.print();
        
        // remove Pet
        /* 
        Animal animal = pets.remove("Hobbes");
        if (animal == null) {
            System.out.println(key + " not found");
        } else {
            System.out.println("Removed: " + key + ", " + animal);
        }
        pets.print();
        */
    }
}
Pets.main(null);
Hobbes is a Calico Kitty and is 1 years old.
Leo is a Gold Lion and is 8 years old.
Porky is a Pink Pig and is 3 years old.
Ro-Ro is a Red Robin and is 7 years old.
Duke is a Brown Dog and is 14 years old.
Midnight is a Black Cat and is 10 years old.

import java.util.HashSet;
import java.util.Set;

public class AnimalSet {
    public static void main(String[] args) {
        // create a new HashSet
        Set<String> animals = new HashSet<>();

        // add some elements to the Set
        animals.add("lion");
        animals.add("dog");
        animals.add("cat");

        // print out the Set
        System.out.println(animals);

        // check if an element is in the Set
        boolean hasLion = animals.contains("lion");
        System.out.println("Has lion: " + hasLion);

        // remove an element from the Set
        animals.remove("lion");
        System.out.println("Removed lion");

        // print out the Set
        System.out.println(animals);

        // add duplicate
        System.out.println("add duplicate dog");
        animals.add("dog");  // no action
        System.out.println(animals);
        // add duplicate
        System.out.println("add pig");
        animals.add("pig");
        System.out.println(animals);

        // using forEach() method with a lambda expression
        animals.forEach(animal -> {
            String message = "I ";
            message += animal.equals("dog") ? "like" : "don't like";
            message += " " + animal + "s " + "for pets";
            System.out.println(message);
        });

    }
}
AnimalSet.main(null);
[cat, dog, lion]
Has lion: true
Removed lion
[cat, dog]
add duplicate dog
[cat, dog]
add pig
[cat, dog, pig]
I don't like cats for pets
I like dogs for pets
I don't like pigs for pets