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

	// Instance data
	private final String name;
	private final int score;

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

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

	// Test data initializer
	public static Users[] user() {
		return new Users[]{
				new Users("Bob", 8),
				new Users("Jane", 10)
		};
	}
	
	/* main to test Animal class
	 * 
	 */
	public static void main(String[] args)
	{
		// Inheritance Hierarchy
		Users[] objs = user();

		// print with title
		Users.setOrder(KeyType.name);
		Users.print(objs);

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

}
Users.main(null);
class [LREPL.$JShell$13C$Users; 2
Generic: Users listed by name
Bob
Jane

class [LREPL.$JShell$13C$Users; 2
Generic: Users listed by score
8
10

Hack #2

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

    public T peekLast() {
        return this.tail.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);
    }
}
import java.util.Random; 
import java.util.ArrayList; 
import java.lang.Math;
/**
 * 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;
    }

    /**
     * Add a list of objects to queue
     */

     
    // RETURN SIZE OF QUEUE
    public int queueSize(Queue<T> queueInput) {
        int size = 0;

        for (T data : queueInput) {
            size++;
        }

        return size; 
    }
    

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

    public void addListHack(T[]... seriesOfObjects) {  //accepts multiple generic T lists
        for (T[] objects: seriesOfObjects)
            for (T data : objects) {
                this.queue.add(data);
                this.count++;
                printQueue();
            }
    }

    public void deleteList(T[]... seriesOfObjects) {  //accepts multiple generic T lists
        for (T[] objects: seriesOfObjects)
            for (T data : objects) {
                this.queue.delete();
                this.count--;
                printQueue();
            }
    }
    /********************************************************************************* */
    // HACK 2
    public void sortSteps(T[]... seriesOfObjects) {
        addList(seriesOfObjects);
        sort();
    }
   
    public void sort() {

        int size = queueSize(queue);
        
        for (int j = 0; j < size - 1; j++) {
            // take first item in queue
            T a = this.queue.peek(); 
            T b = null;
            // remove the first item
            this.queue.delete(); 
            // do a bubble sort
            for (int i = 0; i < size - 1; i++) {

                b = this.queue.peek(); 

                // add the smaller number to the end of the queue
                // this way, the largest number is left at the very back
                if ((Integer)a < (Integer)b) {
                    queue.add(a);
                    a = this.queue.peek(); 
                    this.queue.delete();
                } else {
                    queue.add(b); 
                    this.queue.delete();
                }
            }

            // add the largest number to the back of the queue
            // largest number is always a because it is either:
            // 1. a = this.queue.peek() (last element of queue = biggest)
            // or 2. if b < a, then a is already the biggest number
            queue.add(a);
        }
       
        for (T data : queue) {
            System.out.println(data); 
        }

    }

    /********************************************************************************* */
    // HACK 3

    public void randomSteps(T[]... seriesOfObjects) {
        addList(seriesOfObjects);
        //random();
    }

    public boolean matchElem(int ranNum, int[] order) {
        for (int i = 0; i < order.length; i++) {
                if (ranNum == order[i]) {
                    return true;
                }
        }
        return false; 
    }

    public void random() {
        int size = queueSize(queue);
        Random rand = new Random();
        int randInt = rand.nextInt(size);

        Queue<T> queue2 = new Queue<>();
        Queue<T> queue3 = new Queue<>();


        boolean match = true;

        ArrayList<Integer> originalOrder = new ArrayList<>(); 

        for (int i = 1; i <= size; i++) {
            originalOrder.add(i); 
        }

        while (originalOrder.size() > 0) {
            // some number between 0 and 7
            int num = originalOrder.remove((int)(Math.random() * originalOrder.size()));
            int num2 = originalOrder.remove((int)(Math.random() * originalOrder.size()));

            /* DEBUGGING 
            System.out.println("NUM: " + num); 
            System.out.println("NUM2: " + num2); 
            */

            if (num2 < num) {
                int temp = num2; 
                num2 = num; 
                num = temp; 
            }

            // split queue into queue (bigger #) (345678) and queue2 (smaller #) (12)
            for (int i = 0; i <= num; i++) {
                T a = queue.peek();
                queue2.add(a);
                queue.delete(); 
            }

            // splite queue into queue (678) and queue3 (345)
            // queue2 = 12
            if (num2 == 8) {
                for (int i = 0; i <= num2-num-2; i++) {
                    T a = queue.peek(); 
                    queue3.add(a); 
                    queue.delete(); 
                }
            }else {
                for (int i = 0; i <= num2-num-1; i++) {
                    T a = queue.peek(); 
                    queue3.add(a); 
                    queue.delete(); 
                }
            }



            // finding last elements of queues (these numbers should be swapped)
            T pos1 = queue2.peekLast();
            T pos2 = queue3.peekLast(); 

            /* DEBUGGING 
            System.out.println("pos1: " + pos1);
            System.out.println("pos2: " + pos2);
            */

            // size of two queues
            int queue2Size = queueSize(queue2);
            int queue3Size = queueSize(queue3);

            // reshuffle
            // move q2's numbers to end of q3
            for (int i = 0; i < queue2Size - 1; i++) {
                T a = queue2.peek(); 
                queue3.add(a); 
                queue2.delete(); 
            }
            T queue2Last = queue2.peek();
            queue2.delete(); 

            // move original q3's numbers to q2
            for (int i = 0; i < queue3Size - 1; i++) {
                T a = queue3.peek(); 
                queue2.add(a);
                queue3.delete(); 
            }   
            T queue3Last = queue3.peek();
            queue3.delete(); 
            
            // swap numbers
            queue2.add(queue2Last);
            queue3.add(queue3Last); 

            size = queueSize(queue);
            queue2Size = queueSize(queue2);
            queue3Size = queueSize(queue3);

            for (int i = 0; i < queue3Size; i++) {
                T a = queue3.peek();
                queue.add(a);
                queue3.delete(); 
            }

            for (int i = 0; i < queue2Size; i++) {
                T a = queue2.peek();
                queue.add(a);
                queue2.delete(); 
            }

            for (int i = 0; i < size; i++) {
                T a = queue.peek();
                queue.add(a);
                queue.delete(); 
            }

    

            /*DEBUGGING 
            System.out.println("*************");

            for (T data : queue) {
                System.out.println(data); 
            }
            System.out.println("****************");
            */
        }

        for (T data : queue) {
            System.out.println(data);
        }

       
    }

    /********************************************************************************* */
    public void stack() {
        Stack<T> stacks = new Stack<>();

       for (T data : this.queue) {
            System.out.println(data);

            T a = this.queue.peek();
            System.out.println("A: " + a);
            this.queue.delete(); 

            stacks.push(a);
        }
     
        int size = 0;

        for (T data : stacks) {
            size++;
        }

        /*
        for (T data : stacks) {
            System.out.println(stacks.peek()); 
        }
        stacks.pop(); 
        */

        for (int i = 0; i < size; i++) {
            System.out.println(stacks.peek());
            stacks.pop(); 
        }

    }

 



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

Hack 1

/**
 * 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[] { "seven", "slimy", "snakes", "sallying", "slowly", "slithered", "southward"};
        QueueManager qWords = new QueueManager("Words", words );
        qWords.addListHack(words);
        qWords.deleteList(words);
     
    }
}
QueueTester.main(null);
Words count: 1
Words data: seven 
Words count: 2
Words data: seven slimy 
Words count: 3
Words data: seven slimy snakes 
Words count: 4
Words data: seven slimy snakes sallying 
Words count: 5
Words data: seven slimy snakes sallying slowly 
Words count: 6
Words data: seven slimy snakes sallying slowly slithered 
Words count: 7
Words data: seven slimy snakes sallying slowly slithered southward 
Words count: 6
Words data: slimy snakes sallying slowly slithered southward 
Words count: 5
Words data: snakes sallying slowly slithered southward 
Words count: 4
Words data: sallying slowly slithered southward 
Words count: 3
Words data: slowly slithered southward 
Words count: 2
Words data: slithered southward 
Words count: 1
Words data: southward 
Words count: 0
Words data: 

Hack 2

class QueueTester2 {
    public static void main(String[] args)
    {
        // Create iterable Queue of Integers
        Object[] numbers = new Integer[] { 1, 4, 5, 8};
        Object[] numbers2 = new Integer[] {2, 3, 6, 7};
        QueueManager qNums = new QueueManager("Integers", numbers, numbers2);

        qNums.sortSteps(numbers, numbers2);
    }
}
QueueTester2.main(null);
1
2
3
4
5
6
7
8

Hack 3

class QueueTester3 {
    public static void main(String[] args)
    {
        // Create iterable Queue of Integers
        Object[] numbers = new Integer[] {1, 2, 3, 4, 5, 6, 7, 8};
        QueueManager qNums = new QueueManager("Integers", numbers);

        qNums.randomSteps(numbers);

        qNums.random();
        

        //qNums.random();
    }
}
QueueTester3.main(null);
1
5
6
7
2
8
4
3

Hack 4

class QueueTester4 {
    public static void main(String[] args)
    {
        // Create iterable Queue of Integers
        Object[] numbers = new Integer[] {1, 2, 3};
        QueueManager qNums = new QueueManager("Integers", numbers);

        qNums.stack();


    }
}
QueueTester4.main(null);
1
A: 1
2
A: 2
3
A: 3
3
2
1

Hacks #3

  • An access modifier controls if a variable in a class can be accessed outside of the class. public allows access outside of the class, while private does not. A constructor contains a piece of code that is ran when the object is initialized. Setters and getters are methods that change the value of the variable or retrieve its value. A class also includes a class header and methods. Methods can contain a parameters or be empty.