Tech Talk

Queue<String> queue = new LinkedList<>();  // Queue interface uses LL implementation
queue.add("John");
queue.add("Jane");
queue.add("Bob");
// Collections has a toArray convertion
Object[] arr = queue.toArray();

// Empty queue
System.out.println("Empty Queue");
while (queue.size() > 0) // Interate while size
    System.out.println(queue.remove());

// Iterate of array
System.out.println("Iterate over Array");
for (Object a : arr) // Type is Object from convertion
    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);
class [LREPL.$JShell$21$Alphabet; 26
Generic: Alphabet listed by title
Alphabet: A
Alphabet: B
Alphabet: C
Alphabet: D
Alphabet: E
Alphabet: F
Alphabet: G
Alphabet: H
Alphabet: I
Alphabet: J
Alphabet: K
Alphabet: L
Alphabet: M
Alphabet: N
Alphabet: O
Alphabet: P
Alphabet: Q
Alphabet: R
Alphabet: S
Alphabet: T
Alphabet: U
Alphabet: V
Alphabet: W
Alphabet: X
Alphabet: Y
Alphabet: Z

class [LREPL.$JShell$21$Alphabet; 26
Generic: Alphabet listed by letter
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z

/*
 * 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);
class [LREPL.$JShell$23$Animal; 6
Generic: 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

class [LREPL.$JShell$23$Animal; 6
Generic: Animal listed by name
Lion
Pig
Robin
Cat
Kitty
Dog

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 [LREPL.$JShell$25$Cupcake; 9
Generic: Cupcake listed by title
Cupcake: Red Velvet, Red, 4
Cupcake: Orange, Orange, 5
Cupcake: Lemon, Yellow, 6
Cupcake: Apple, Green, 7
Cupcake: Blueberry, Blue, 8
Cupcake: Blackberry, Purple, 9
Cupcake: Strawberry, Pink, 10
Cupcake: Vanilla, Tan, 11
Cupcake: Chocolate, Brown, 12

class [LREPL.$JShell$25$Cupcake; 9
Generic: Cupcake listed by flavor
Red Velvet
Orange
Lemon
Apple
Blueberry
Blackberry
Strawberry
Vanilla
Chocolate

MortLingo

public class Lingo extends Generics {
	// Class data
	public static KeyTypes key = KeyType.lang;  // static initializer
	public static void setOrder(KeyTypes key) {Lingo.key = key;}
	public enum KeyType implements KeyTypes {lang, level, correct}

	// Instance data
	private final String lang;
	private final String level;
    private final int correct;

	// Constructor

	Lingo(String lang, String level, int correct)
	{
		this.setType("Lingo");
		this.lang = lang;
		this.level = level;
		this.correct = correct;
	}

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

	/* 'Generics' requires toString override
	 * toString provides data based off of Static Key setting
	 */
	@Override
	public String toString() {		
		String output="";
		if (KeyType.lang.equals(this.getKey())) {
			output += this.lang;
		} else if (KeyType.level.equals(this.getKey())) {
			output += this.level;
		} else if (KeyType.correct.equals(this.getKey())) {
			output += + this.correct;
		} else {
			output = super.getType() + ": " + this.lang + ", " + this.level + ", " + this.correct;
		}
		return output;
	}

	// Test data initializer
	public static Lingo[] languages() {
		return new Lingo[]{
				new Lingo("Java", "Mastery", 9),
			    new Lingo("JavaScript", "Mastery", 10),
			    new Lingo("C#", "Beginner", 4),
                new Lingo("Python", "Intermediate", 7),
		};
	}
	
	public static void main(String[] args)
	{
		// Inheritance Hierarchy
		Lingo[] objs = languages();

		// print with language
		Lingo.setOrder(KeyType.lang);
		Lingo.print(objs);

		// print level 
		Lingo.setOrder(KeyType.level);
		Lingo.print(objs);

		// print correct out of 10
		Lingo.setOrder(KeyType.correct);
		Lingo.print(objs);
	}
	
}
Lingo.main(null);
class [LREPL.$JShell$40F$Lingo; 4
Generic: Lingo listed by lang
Java
JavaScript
C#
Python

class [LREPL.$JShell$40F$Lingo; 4
Generic: Lingo listed by level
Mastery
Mastery
Beginner
Intermediate

class [LREPL.$JShell$40F$Lingo; 4
Generic: Lingo listed by correct
9
10
4
7

CB video notes & definitions

  • constructing an object using a class, and using an object
  • uses object.method because it is an accessor method that returns a variable that returns the method ex: String location = teacher.getLocation(); or teacher.changeLocation("Florida");

  • using static methods means that you can use the methods without creating an object, example being the Math class where you can say class.method instead of object.method

  • string class object where you can set it equal to a word like "theater" word.length

  • contructor is used to create the instance of the class

  • modifiers are used to change the access to a method, like public, private, etc

  • setters/getters are used to protect the data in a class, getters return the value while setters sets or updates a value

Linked Lists & Queues

/**
 *  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();
    }
}
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.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);
Words count: 7
Words data: seven slimy snakes sallying slowly slithered southward 
Integers count: 10
Integers data: 0 1 2 3 4 5 6 7 8 9 
My Generics count: 41
My Generics data: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Lion Pig Robin Cat Kitty Dog Red Velvet Orange Lemon Apple Blueberry Blackberry Strawberry Vanilla Chocolate 
Mixed count: 58
Mixed data: Start seven slimy snakes sallying slowly slithered southward 0 1 2 3 4 5 6 7 8 9 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Lion Pig Robin Cat Kitty Dog Red Velvet Orange Lemon Apple Blueberry Blackberry Strawberry Vanilla Chocolate End 

Hack Challenges

// Hack 1
public class QueueExample {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<String>();

        // Adding elements to the queue
        queue.add("seven");
        System.out.println("Enqueued data: " + "seven");
        printQueue(queue);

        queue.add("slimy");
        System.out.println("Enqueued data: " + "slimy");
        printQueue(queue);

        queue.add("snakes");
        System.out.println("Enqueued data: " + "snakes");
        printQueue(queue);

        queue.add("sallying");
        System.out.println("Enqueued data: " + "sallying");
        printQueue(queue);

        queue.add("slowly");
        System.out.println("Enqueued data: " + "slowly");
        printQueue(queue);

        queue.add("slithered");
        System.out.println("Enqueued data: " + "slithered");
        printQueue(queue);

        queue.add("southward");
        System.out.println("Enqueued data: " + "southward");
        printQueue(queue);

        // Removing elements from the queue
        String data =queue.remove();

        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);

        data = queue.remove();
        System.out.println("Dequeued data: " + data);
        printQueue(queue);
    }

    // Helper method to print the contents of the queue
    public static void printQueue(Queue<String> queue) {
        System.out.println("Words count: " + queue.size() + ", data: " + String.join(" ", queue));
        System.out.println();
    }
}

QueueExample.main(null);
Enqueued data: seven
Words count: 1, data: seven

Enqueued data: slimy
Words count: 2, data: seven slimy

Enqueued data: snakes
Words count: 3, data: seven slimy snakes

Enqueued data: sallying
Words count: 4, data: seven slimy snakes sallying

Enqueued data: slowly
Words count: 5, data: seven slimy snakes sallying slowly

Enqueued data: slithered
Words count: 6, data: seven slimy snakes sallying slowly slithered

Enqueued data: southward
Words count: 7, data: seven slimy snakes sallying slowly slithered southward

Dequeued data: seven
Words count: 6, data: slimy snakes sallying slowly slithered southward

Dequeued data: slimy
Words count: 5, data: snakes sallying slowly slithered southward

Dequeued data: snakes
Words count: 4, data: sallying slowly slithered southward

Dequeued data: sallying
Words count: 3, data: slowly slithered southward

Dequeued data: slowly
Words count: 2, data: slithered southward

Dequeued data: slithered
Words count: 1, data: southward

Dequeued data: southward
Words count: 0, data: 

//Hack 2 - merge 2 queues
Queue<Integer> questionNums1 = new LinkedList<>();
//offer adds an element to the end of the queue and 
//returns a boolean value indicating whether the operation was successful
questionNums1.add(1);
questionNums1.add(4);
questionNums1.add(5);
questionNums1.add(8);

Queue<Integer> questionNums2 = new LinkedList<>();
questionNums2.add(2);
questionNums2.add(3);
questionNums2.add(6);
questionNums2.add(7);

Queue<Integer> mergedQueue = new LinkedList<>();

while (!questionNums1.isEmpty() && !questionNums2.isEmpty()) {
    if (questionNums1.peek() < questionNums2.peek()) { //Retrieve the first element from each queue using the peek() method
        //peek method returns the element at the front of the queue without removing it
        mergedQueue.offer(questionNums1.poll());
    } else { //Compare the two elements 
        //enqueue the smaller one to the new queue using the offer() method.
        mergedQueue.offer(questionNums2.poll());
    }//repeat
}

mergedQueue.addAll(questionNums1);
mergedQueue.addAll(questionNums2);

System.out.println("Python Question # Order: " + mergedQueue);
Python Question # Order: [1, 2, 3, 4, 5, 6, 7, 8]
import java.util.Queue;
import java.util.LinkedList;
import java.util.Random;

public class ShuffleQueue {
    public static void shuffle(Queue<String> queue) {
        Random rand = new Random();
//static shuffle method that takes a Queue of strings as its argument and shuffles the elements
        for (int i = 0; i < queue.size(); i++) {
            int randomIndex = rand.nextInt(queue.size());
            String temp = queue.peek();
            //view or peek at the element at the front of the queue without removing it
            for (int j = 0; j < randomIndex; j++) {
                queue.add(queue.remove());
            }//iterating through the queue and swapping
            // each element with another element at a random position in the queue.
            queue.remove();
            for (int j = 0; j < randomIndex; j++) {
                queue.add(queue.remove());
            }
            queue.add(temp);
        }
    }
    //Random object to generate random indices within the size of the queue
    //combination of remove and add methods to move elements around in the queue

    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        queue.add("Python");
        queue.add("JavaScript");
        queue.add("C#");
        queue.add("Java");

        System.out.println("Original queue: " + queue);

        shuffle(queue);

        System.out.println("Shuffled queue: " + queue);
    }
}
ShuffleQueue.main(null);
Original queue: [Python, JavaScript, C#, Java]
Shuffled queue: [Java, Python, C#, C#]
//Hack 4
Queue<Integer> queue = new LinkedList<>();
//Create a new empty stack to store the elements of the queue
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
queue.offer(5);

Stack<Integer> stack = new Stack<>();
while (!queue.isEmpty()) {
    stack.push(queue.poll());
}
//Dequeue all elements from the original queue and push them onto the stack
Queue<Integer> reversedQueue = new LinkedList<>();
while (!stack.isEmpty()) {
    reversedQueue.offer(stack.pop());
}//Create a new empty queue to store the reversed elements
// pop removes and returns the top element of the stack

System.out.println("Original Question Numbers: " + queue);
System.out.println("Reversed Question Numbers: " + reversedQueue);
Original Question Numbers: []
Reversed Question Numbers: [5, 4, 3, 2, 1]
import java.util.Queue;
import java.util.Stack;

public class Languages {
    public static void reverse(Queue<String> queue) {
        Stack<String> stack = new Stack<>();
//The reverse method creates a new Stack object, 
//then iterates through the elements in the queue, removing them one by one and pushing them onto the stack
        while (!queue.isEmpty()) {
            stack.push(queue.remove());
        }

        while (!stack.isEmpty()) {
            queue.add(stack.pop()); //the method iterates 
            //through the elements in the stack, popping them off one by one and adding them back to the queue
        }
    }
}
System.out.println("Reversed queue of languages: "+queue);
Reversed queue of languages: [Java, C#, JavaScript, Python]