public abstract class Generics {
	public final String masterType = "Generic";
	private String type;	// extender should define their data type

	// generic 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();

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

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

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

		System.out.println();
	}
}
public class Language extends Generics {
	// Class data
	public static KeyTypes key = KeyType.language;  // static initializer
	public static void setOrder(KeyTypes key) {Language.key = key;}
	public enum KeyType implements KeyTypes {model, language, type, year}

	// Instance data
	private final String language;
	private final String type;
	private final int year;

	// Constructor
	Language(String language, String type, int year)
	{
		this.setType("Language");
		this.language = language;
		this.type = type;
		this.year = year;
	}

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

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

	// Test data initializer
	public static Language[] Language() {
		return new Language[]{
				new Language("Java", "OO",1995),
			    new Language("HTML", "MarkUp",1999),
			    new Language("CSS", "Style",1996),
			    new Language("Markdown", "Markup",2004),
			    new Language("Javascript", "Frontend",1995),
			    new Language("Python", "OO",1991),
			    new Language("SQL", "Query",1970),
			    new Language("C++", "OO",1983),
		};
	}
	
	public static void main(String[] args)
	{
		// Inheritance Hierarchy
		Language[] objs = Language();

		Language.setOrder(KeyType.model);
		Language.print(objs);
		// print with title
		Language.setOrder(KeyType.language);
		Language.print(objs);

	}
	
}
Language.main(null);
class [LREPL.$JShell$15E$Language; 8
Generic: Language listed by model
Language: Java, OO, 1995
Language: HTML, MarkUp, 1999
Language: CSS, Style, 1996
Language: Markdown, Markup, 2004
Language: Javascript, Frontend, 1995
Language: Python, OO, 1991
Language: SQL, Query, 1970
Language: C++, OO, 1983

class [LREPL.$JShell$15E$Language; 8
Generic: Language listed by language
Java
HTML
CSS
Markdown
Javascript
Python
SQL
C++

public class language extends Generics {
	// Class data
	public static KeyTypes key = KeyType.title;  // static initializer
	public static void setOrder(KeyTypes key) { language.key = key; }
	public enum KeyType implements KeyTypes {title, name, age, language}

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

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

	/* 'Generics' requires getKey to help enforce KeyTypes usage */
	@Override
	protected KeyTypes getKey() { return language.key; }
	
	/* 'Generics' 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.language.equals(this.getKey())) {
			output += this.language;
		} else {
			output += super.getType() + ": " + this.name + ", " + this.language + ", " + this.age;
		}
		return output;
		
	}

	// Test data initializer
	public static language[] languages() {
		return new language[]{
				new language("Java", 6, "Object-Oriented"),
				new language("Python", 2, "Object-Oriented"),
				new language("HTML", 9, "HyperTextMarkup"),
				new language("CSS", 5, "Style"),
				new language("Javascript", 3, "Functional-f=Frontend"),
				new language("Markdown", 1, "Markup")
		};
	}
	
	/* main to test Animal class
	 * 
	 */
	public static void main(String[] args)
	{
		// Inheritance Hierarchy
		language[] objs = languages();

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

		// print name only
		language.setOrder(KeyType.name);
		language.print(objs);
	}

}
language.main(null);
class [LREPL.$JShell$27C$language; 6
Generic: language listed by title
language: Java, Object-Oriented, 6
language: Python, Object-Oriented, 2
language: HTML, HyperTextMarkup, 9
language: CSS, Style, 5
language: Javascript, Functional-f=Frontend, 3
language: Markdown, Markup, 1

class [LREPL.$JShell$27C$language; 6
Generic: language listed by name
Java
Python
HTML
CSS
Javascript
Markdown

/**
 *  Implementation of a Double Linked List;  forward and backward links point to adjacent Nodes.
 *
 */

 public class LinkedList<T>
 {
     private T data;
     private LinkedList<T> prevNode, nextNode;
 
     /**
      *  Constructs a new element
      *
      * @param  data, data of object
      * @param  node, previous node
      */
     public LinkedList(T data, LinkedList<T> node)
     {
         this.setData(data);
         this.setPrevNode(node);
         this.setNextNode(null);
     }
 
     /**
      *  Clone an object,
      *
      * @param  node  object to clone
      */
     public LinkedList(LinkedList<T> node)
     {
         this.setData(node.data);
         this.setPrevNode(node.prevNode);
         this.setNextNode(node.nextNode);
     }
 
     /**
      *  Setter for T data in DoubleLinkedNode object
      *
      * @param  data, update data of object
      */
     public void setData(T data)
     {
         this.data = data;
     }
 
     /**
      *  Returns T data for this element
      *
      * @return  data associated with object
      */
     public T getData()
     {
         return this.data;
     }
 
     /**
      *  Setter for prevNode in DoubleLinkedNode object
      *
      * @param node, prevNode to current Object
      */
     public void setPrevNode(LinkedList<T> node)
     {
         this.prevNode = node;
     }
 
     /**
      *  Setter for nextNode in DoubleLinkedNode object
      *
      * @param node, nextNode to current Object
      */
     public void setNextNode(LinkedList<T> node)
     {
         this.nextNode = node;
     }
 
 
     /**
      *  Returns reference to previous object in list
      *
      * @return  the previous object in the list
      */
     public LinkedList<T> getPrevious()
     {
         return this.prevNode;
     }
 
     /**
      *  Returns reference to next object in list
      *
      * @return  the next object in the list
      */
     public LinkedList<T> getNext()
     {
         return this.nextNode;
     }
 
 }
import java.util.Iterator;

/**
 * Queue Iterator
 *
 * 1. "has a" current reference in Queue
 * 2. supports iterable required methods for next that returns a generic T Object
 */
class QueueIterator<T> implements Iterator<T> {
    LinkedList<T> current;  // current element in iteration

    // QueueIterator is pointed to the head of the list for iteration
    public QueueIterator(LinkedList<T> head) {
        current = head;
    }

    // hasNext informs if next element exists
    public boolean hasNext() {
        return current != null;
    }

    // next returns data object and advances to next position in queue
    public T next() {
        T data = current.getData();
        current = current.getNext();
        return data;
    }
}

/**
 * Queue: custom implementation
 * @author     John Mortensen
 *
 * 1. Uses custom LinkedList of Generic type T
 * 2. Implements Iterable
 * 3. "has a" LinkedList for head and tail
 */
public class Queue<T> implements Iterable<T> {
    LinkedList<T> head = null, tail = null;

    /**
     *  Add a new object at the end of the Queue,
     *
     * @param  data,  is the data to be inserted in the Queue.
     */
    public void add(T data) {
        // add new object to end of Queue
        LinkedList<T> tail = new LinkedList<>(data, null);

        if (this.head == null)  // initial condition
            this.head = this.tail = tail;
        else {  // nodes in queue
            this.tail.setNextNode(tail); // current tail points to new tail
            this.tail = tail;  // update tail
        }
    }

    /**
     *  Returns the data of head.
     *
     * @return  data, the dequeued data
     */
    public T delete() {
        T data = this.peek();
        if (this.tail != null) { // initial condition
            this.head = this.head.getNext(); // current tail points to new tail
            if (this.head != null) {
                this.head.setPrevNode(tail);
            }
        }
        return data;
    }

    /**
     *  Returns the data of head.
     *
     * @return  this.head.getData(), the head data in Queue.
     */
    public T peek() {
        return this.head.getData();
    }

    /**
     *  Returns the head object.
     *
     * @return  this.head, the head object in Queue.
     */
    public LinkedList<T> getHead() {
        return this.head;
    }

    /**
     *  Returns the tail object.
     *
     * @return  this.tail, the last object in Queue
     */
    public LinkedList<T> getTail() {
        return this.tail;
    }

    /**
     *  Returns the iterator object.
     *
     * @return  this, instance of object
     */
    public Iterator<T> iterator() {
        return new QueueIterator<>(this.head);
    }
}
/**
 * Queue Manager
 * 1. "has a" Queue
 * 2. support management of Queue tasks (aka: titling, adding a list, printing)
 */
class QueueManager<T> {
    // queue data
    private final String name; // name of queue
    private int count = 0; // number of objects in queue
    public final Queue<T> queue = new Queue<>(); // queue object

    /**
     *  Queue constructor
     *  Title with empty queue
     */
    public QueueManager(String name) {
        this.name = name;
    }

    /**
     *  Queue constructor
     *  Title with series of Arrays of Objects
     */
    public QueueManager(String name, T[]... seriesOfObjects) {
        this.name = name;
        this.addList(seriesOfObjects);
    }

    /**
     * Add a list of objects to queue
     */
    public void addList(T[]... seriesOfObjects) {  //accepts multiple generic T lists
        for (T[] objects: seriesOfObjects)
            for (T data : objects) {
                this.queue.add(data);
                this.count++;
            }
    }

    /**
     * Print any array objects from queue
     */
    public void printQueue() {
        System.out.println(this.name + " count: " + count);
        System.out.print(this.name + " data: ");
        for (T data : queue)
            System.out.print(data + " ");
        System.out.println();
    }
}
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