Generics and Collections + Challenge 1
Generics and Collections
Queue<String> queue = new LinkedList<>(); // Queue interface uses LL implementation
queue.add("John");
queue.add("Jane");
queue.add("Bob");
// Collections has a toArray conversion
Object[] arr = queue.toArray();
// Iterate of array
System.out.println("Iterate over Array");
for (Object a : arr){
// Type is Object from conversion
System.out.println(a);
// remove() method is called to remove and print the next element in the queue
}
// Empty queue
System.out.println("Empty Queue");
while (queue.size() > 0) // Interate while size
System.out.println(queue.remove());
// remove() method is called to remove and print the next element in the queue
System.out.println(queue);
/* This is wrapper class...
Objective would be to push more functionality into this Class to enforce consistent definition
*/
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 smallSize to establish key order
public abstract String toString();
// static print method smallSize by extended classes
public static void print(Generics[] objs) {
// print 'Object' properties
// System.out.println(objs.getClass() + " " + objs.length);
System.out.println(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 Turtle extends Generics {
public static KeyTypes key = KeyType.title;
public static void setOrder(KeyTypes key) { Turtle.key = key; }
public enum KeyType implements KeyTypes {title, name, age, weight, smallSize}
private final String name;
private final int age;
private final double weight;
private final boolean smallSize;
public Turtle(String name, int age, double weight, boolean smallSize)
{
super.setType("Turtle");
this.name = name;
this.age = age;
this.weight = weight;
this.smallSize = smallSize;
}
@Override
protected KeyTypes getKey() { return Turtle.key; }
@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.weight.equals(this.getKey())) {
output += this.weight;
} else if (KeyType.smallSize.equals(this.getKey())) {
output += this.smallSize;
} else {
output += super.getType() + ": " + this.name + ", " + this.smallSize + ", " + this.age + ", " + this.weight;
}
return output;
}
// Test data initializer
public static Turtle[] Turtles() {
return new Turtle[]{
new Turtle("Shellbert", 5, 2.22, false),
new Turtle("Eggbert", 4, 3.34, true),
new Turtle("Seabert", 3, 6.54, true)
};
}
public static void main(String[] args)
{
// Inheritance Hierarchy
Turtle[] objs = Turtles();
// print with title
Turtle.setOrder(KeyType.title);
Turtle.print(objs);
// print name only
Turtle.setOrder(KeyType.name);
Turtle.print(objs);
// print by weight only
Turtle.setOrder(KeyType.weight);
Turtle.print(objs);
}
}
Turtle.main(null);
/**
* 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();
}
}
/**
* Driver Class
* Tests queue with string, integers, and mixes of Classes and types
*/
class QueueTester {
public static void main(String[] args)
{
// Create iterable Queue of NCS Generics
Turtle.setOrder(Turtle.KeyType.name);
// Illustrates use of a series of repeating arguments
QueueManager qGenerics = new QueueManager("My Generics", Turtle.Turtles());
qGenerics.printQueue();
qGenerics.queue.add(new Turtle("Beachbert", 5, 5.22, false));
qGenerics.printQueue();
qGenerics.queue.add(new Turtle("Sheldon", 7, 4.42, false));
qGenerics.queue.delete();
qGenerics.printQueue();
qGenerics.queue.delete();
qGenerics.printQueue();
}
}
QueueTester.main(null);
class Main {
public static void main(String[] args) {
int[][] arr1 = {{0,1,2}, {1, 2, 0}, {2, 0, 1}};
int[][] arr2 = {{0,1,2}, {1, 2, 0}, {2, 1, 0}};
printArray(arr1);
System.out.println(ArrayTester.isLatin(arr1));
printArray(arr2);
System.out.println(ArrayTester.isLatin(arr2));
}
public static void printArray(int[][] arr) {
for(int[] i: arr) {
for(int j: i) {
System.out.print(j + "\t");
}
System.out.println();
}
}
}
class ArrayTester {
public static int[] getColumn(int[][] arr, int col) {
int[] column = new int[arr.length];
for(int i = 0; i < arr.length; i++) {
column[i] = arr[i][col];
}
return column;
}
public static boolean hasAllValues(int[] arr1, int[] arr2) {
for(int i = 0; i < arr1.length; i++) {
boolean found = false;
for(int j = 0; j < arr2.length; j++) {
if(arr1[i] == arr2[j]) {
found = true;
break;
}
}
if(!found) {
return false;
}
}
return true;
}
public static boolean containsDuplicates(int[] arr) {
for(int i = 0; i < arr.length - 1; i++) {
if(arr[i] == arr[i+1]) {
return true;
}
}
System.out.print("Result: ");
return false;
}
public static boolean isLatin(int[][] square) {
if(containsDuplicates(square[0])) {
return false;
}
for(int i = 1; i < square.length; i++) {
if(!hasAllValues(square[0], square[i]) || !hasAllValues(square[0], getColumn(square, i))) {
return false;
}
}
return true;
}
}
Main.main(null);
/**
* Driver Class
* Tests queue with string, integers, and mixes of Classes and types
*/
class QueueTester {
public static void main(String[] args)
{
// Create iterable Queue of Words
Object[] words = new String[] { "Serendipity", "Quixotic", "Melancholy", "Perfidious", "Ephemeral"};
QueueManager qWords = new QueueManager("Words", words);
qWords.printQueue();
// Create iterable Queue of Integers
Object[] numbers = new Integer[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
QueueManager qNums = new QueueManager("Integers", numbers );
qNums.printQueue();
}
}
QueueTester.main(null);
import java.util.Iterator;
public class LinkedList<T> {
private T data;
private LinkedList<T> prevNode, nextNode;
// Create new node with T data and reference to previous LinkedList<T> node
public LinkedList(T data, LinkedList<T> node) {
setData(data);
setPrevNode(node);
setNextNode(null);
}
// Create new node using copy
public LinkedList(LinkedList<T> node) {
setData(node.data);
setPrevNode(node.prevNode);
setNextNode(node.nextNode);
}
// Getters
public T getData() {
return this.data;
}
public LinkedList<T> getPrev() {
return this.prevNode;
}
public LinkedList<T> getNext() {
return this.nextNode;
}
// Setters
public void setData(T data) {
this.data = data;
}
public void setPrevNode(LinkedList<T> node) {
this.prevNode = node;
}
public void setNextNode(LinkedList<T> node) {
this.nextNode = node;
}
}
/**
* 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() {
try {
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;
} catch (Exception E) {
return null;
}
}
/**
* Returns the data of head.
*
* @return this.head.getData(), the head data in Queue.
*/
public T peek() {
try {
return this.head.getData();
} catch (Exception E) {
return null;
}
}
/**
* 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++;
}
}
// Challenge 1
public T delete() {
count--;
return this.queue.delete();
}
/**
* 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();
}
}
/**
* Driver Class
* Tests queue with string, integers, and mixes of Classes and types
*/
class QueueTester {
public static void main(String[] args)
{
// Create iterable Queue of Words
Object[] words = new String[] { "Serendipity", "Quixotic", "Melancholy", "Perfidious", "Ephemeral"};
QueueManager qWords = new QueueManager("Words", words );
qWords.printQueue();
while (qWords.delete() != null) {
qWords.printQueue();
}
}
}
QueueTester.main(null);