Generic Types and Collections Week 26
Classes and Object
Parts of a class:
- Constructor header with parameters
- Instance variables (private, public)
- Accessor methods (return value: int, string, etc)
- Mutator methods (changes values)
Instantiate an Object:
- Class object = new Class(parameters)
Using Methods:
- object.method()
- Math class --> Math.method()
- Make sure you're solid on this for the test
Interface vs. Implementation
- Interface: where you define the methods you have in the class
- Implementation: instantiate objects and methods
Complexity
- The time and space an algorithm takes (space complexity)
- Ex: multiple loops
Linked Lists
- Another data structure
- LinkedList
linky = new LinkedList ();</li> - Similarly to an arrayList there are a lot of methods that come with it
- Very flexible
- Each value in the list knows the element before and after
- Iterator object --> must import java.util
- Maintains insertion order
</ul> </div> </div> </div>Queues
- Queue
bbqLine = new LinkedLists ();</li> - There are a bunch of methods that come with it
- Can take out someone using .poll(); method
- Can see the first element using .peek();
</ul> </div> </div> </div>Stacks
- Last in first out
- Contains basic push and pop operations
- public class Stack
extends Vector </li> - Subclass of Vector
- Must import java.util.stack
</ul> </div> </div> </div>Queue<String> queue = new LinkedList<>(); // Queue interface uses linked list implementation queue.add("John"); queue.add("Jane"); queue.add("Bob"); //Collection has a toArray conversion Object[] arr = queue.toArray(); //Empty queue System.out.println("Empty Queue"); while (queue.size() > 0) System.out.println(queue.remove()); //Iterate of array System.out.println("Iterate over Array"); for (Object a : arr) //type becomes Object because of conversion // objects have a toString method built into it, so it prints as a String System.out.println(a);
/* 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 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 Alphabet extends Generics { // Class data public static KeyTypes key = KeyType.title; // static initializer public static void setOrder(KeyTypes key) {Alphabet.key = key;} public enum KeyType implements KeyTypes {title, letter} private static final int size = 26; // constant used in data initialization // Instance data private final char letter; /* * single letter object */ public Alphabet(char letter) { this.setType("Alphabet"); this.letter = letter; } /* 'Generics' requires getKey to help enforce KeyTypes usage */ @Override protected KeyTypes getKey() { return Alphabet.key; } /* 'Generics' requires toString override * toString provides data based off of Static Key setting */ @Override public String toString() { String output=""; if (KeyType.letter.equals(this.getKey())) { output += this.letter; } else { output += super.getType() + ": " + this.letter; } return output; } // Test data initializer for upper case Alphabet public static Alphabet[] alphabetData() { Alphabet[] alphabet = new Alphabet[Alphabet.size]; for (int i = 0; i < Alphabet.size; i++) { alphabet[i] = new Alphabet( (char)('A' + i) ); } return alphabet; } /* * main to test Animal class */ public static void main(String[] args) { // Inheritance Hierarchy Alphabet[] objs = alphabetData(); // print with title Alphabet.setOrder(KeyType.title); Alphabet.print(objs); // print letter only Alphabet.setOrder(KeyType.letter); Alphabet.print(objs); } } Alphabet.main(null);
/* * Animal class extends Generics and defines abstract methods */ public class Animal extends Generics { // 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; } /* 'Generics' requires getKey to help enforce KeyTypes usage */ @Override protected KeyTypes getKey() { return Animal.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.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); // print name only Animal.setOrder(KeyType.name); Animal.print(objs); } } Animal.main(null);
public class Cupcake extends Generics { // Class data public static KeyTypes key = KeyType.title; // static initializer public static void setOrder(KeyTypes key) {Cupcake.key = key;} public enum KeyType implements KeyTypes {title, flavor, frosting, sprinkles} // Instance data private final String frosting; private final int sprinkles; private final String flavor; // Constructor Cupcake(String frosting, int sprinkles, String flavor) { this.setType("Cupcake"); this.frosting = frosting; this.sprinkles = sprinkles; this.flavor = flavor; } /* 'Generics' requires getKey to help enforce KeyTypes usage */ @Override protected KeyTypes getKey() { return Cupcake.key; } /* 'Generics' requires toString override * toString provides data based off of Static Key setting */ @Override public String toString() { String output=""; if (KeyType.flavor.equals(this.getKey())) { output += this.flavor; } else if (KeyType.frosting.equals(this.getKey())) { output += this.frosting; } else if (KeyType.sprinkles.equals(this.getKey())) { output += "00" + this.sprinkles; output = output.substring(output.length() - 2); } else { output = super.getType() + ": " + this.flavor + ", " + this.frosting + ", " + this.sprinkles; } return output; } // Test data initializer public static Cupcake[] cupcakes() { return new Cupcake[]{ new Cupcake("Red", 4, "Red Velvet"), new Cupcake("Orange", 5, "Orange"), new Cupcake("Yellow", 6, "Lemon"), new Cupcake("Green", 7, "Apple"), new Cupcake("Blue", 8, "Blueberry"), new Cupcake("Purple", 9, "Blackberry"), new Cupcake("Pink", 10, "Strawberry"), new Cupcake("Tan", 11, "Vanilla"), new Cupcake("Brown", 12, "Chocolate"), }; } public static void main(String[] args) { // Inheritance Hierarchy Cupcake[] objs = cupcakes(); // print with title Cupcake.setOrder(KeyType.title); Cupcake.print(objs); // print flavor only Cupcake.setOrder(KeyType.flavor); Cupcake.print(objs); } } Cupcake.main(null);
class Monkies extends Generics { // Class data, generics framework public static KeyTypes key = KeyType.title; public static void setOrder(KeyTypes key) { Monkies.key = key; } public enum KeyType implements KeyTypes {title, name, age, color, size, weight} // All of our data private final String name; private final int age; private final String color; private final String size; private final int weight; // Monkies constructor public Monkies (String name, int age, String color, String size, int weight){ super.setType("Monkey"); this.name = name; this.age = age; this.color = color; this.size = size; this.weight = weight; } //Helps enforce KeyTypes usage @Override protected KeyTypes getKey() { return Monkies.key; } //Requires toString override @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 if (KeyType.size.equals(this.getKey())){ output += this.size; } else if (KeyType.weight.equals(this.getKey())){ output += "00" + this.age; output = output.substring((output.length()- 2)); } else { output += super.getType() + ": " + this.name + ", " + this.color + ", " + this.age + ", " + this.size + ", " + this.weight; } return output; } //test data public static Monkies[] monkies(){ return new Monkies[]{ new Monkies("Mr. Gorilla", 20, "Purple", "Large", 400), //gorilla new Monkies("Chimpy", 3, "Blue", "Medium", 70), //chimpanzee new Monkies("Mrs. Orangutan", 25, "Green", "Medium", 100), //oragutan new Monkies("Babson", 15, "Orange", "Small", 40), //baboon }; } //tests Monkies class public static void main(String[] args){ Monkies[] objs = monkies(); Monkies.setOrder(KeyType.title); Monkies.print(objs); } } Monkies.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); this.deleteList(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) { //adds a count for every iteration this.count++; //prints enqueued data System.out.println("Enqueued data: " + data); //inserts data at the end of the queue this.queue.add(data); //prints System.out.print(this.name + "count: " + count + ", data: "); //for each element x in the queue made from "this.queue.add(data)" for (T x : queue){ //prints element and a space System.out.print(x + " "); } System.out.println(); System.out.println(); } } /** * Add a list of objects to queue */ public void deleteList(T[]... seriesOfObjects) { //accepts multiple generic T lists for (T[] objects: seriesOfObjects) for (T data : objects) { //subtracts a count for every iteration this.count--; //prints enqueued data System.out.println("Enqueued data: " + data); //inserts at the end of the queue this.queue.delete(); //prints System.out.print(this.name + "count: " + count + ", data: "); //for each element x in the queue made from "this.queue.add(data)" for (T x : queue){ //prints element and a space System.out.print(x + " "); } System.out.println(); System.out.println(); } } /*peek into the first term of the two queues, compare them to see which is smaller then add the smaller one to a third queue and delete the term from the queue that had the smaller term. Repeat using a loop */ public void mergeQueue(){ } /** * 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) { // Merge queues Object [] nums1 = new Integer[]{ 1, 4, 5, 8 }; Object [] nums2 = new Integer[]{ 2, 3, 6, 7 }; // Create iterable Queue of Words Object[] words = new String[] {"Mr. Gorilla", "Chimpy", "Babson", "Mrs. Orangutan" }; 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(); // Create iterable Queue of NCS Generics Animal.setOrder(Animal.KeyType.name); Alphabet.setOrder(Alphabet.KeyType.letter); Cupcake.setOrder(Cupcake.KeyType.flavor); // Illustrates use of a series of repeating arguments QueueManager qGenerics = new QueueManager("My Generics", Alphabet.alphabetData(), Animal.animals(), Cupcake.cupcakes() ); qGenerics.printQueue(); // Create iterable Queue of Mixed types of data /* QueueManager qMix = new QueueManager("Mixed"); qMix.queue.add("Start"); qMix.addList( words, numbers, Alphabet.alphabetData(), Animal.animals(), Cupcake.cupcakes() ); qMix.queue.add("End"); qMix.printQueue(); */ } } QueueTester.main(null);