07a: Queue ADT

ICS211, Fall 2012
Dr. Zach

(switch view)

Status check

Queue ADT

Queue Behavior

Method names not as standardized as for stack

Queue Use

Queue<Integer> q = new Queue<Integer>();
q.offer(4);
q.offer(7);
q.offer(9);
System.out.println(q.size());  // 3
System.out.println(q.peek());  // 4
q.poll();                     
System.out.println(q.poll());  // 7

Implementation options

Array-based Queue

Array-based Queue Implementation

public class Queue<E> {

  private static final int CAPACITY = 5;

  private E[] items;
  private int front;  //points at first item
  private int back;   //first blank spot

  public Queue() {
    //use one extra cell so never full, so front == back always means empty
    @SuppressWarnings("unchecked")  //more on this later...
    E[] array = (E[]) new Object[CAPACITY + 1];
    items = array;
    back = 0;
    front = 0;
  }

  public void offer(E item) {
    if (this.size() == CAPACITY) {
      //Implementation-level restriction: would be nice to avoid this...
      throw new IllegalStateException("Queue is full.");
    }
    this.items[back] = item;
    this.back = (this.back + 1) % items.length;
  }

  public E peek() {
    if (this.size() == 0) {
      throw new IllegalStateException("Queue is empty.");
    }
    return this.items[front];
  }

  public E poll() {
    E item = this.peek();  //throws exception if empty
    this.front = (this.front + 1) % items.length;
    return item;
  }

  public int size() {
    return (this.back + items.length - this.front) % items.length;
  }
}

Big-Os?

Array-based Queue - Growth

Node-based Queue implementation

Other Queue options?

ADT behavior vs efficiency

Java: Generics

Revisited

Pre-generics ArrayList use

Also before autoboxing

public static void main(String[] args) {
  ArrayList numbers = new ArrayList();
  numbers.add(new Integer(2));
  numbers.add(new Integer(4));
  numbers.add(new Integer(5));
  int total = product(numbers);
  System.out.println(total);
}

public static int product(ArrayList nums) {
  int product = 1;
  for (int i = 0; i < nums.size(); i++) {
    Integer n = (Integer) nums.get(i); //nums.get(i) returns an Object
    product *= n.intValue();
  }
  return product;
}

Modern ArrayList use

(Still no autoboxing in this example)

public static void main(String[] args) {
  ArrayList<Integer> numbers = new ArrayList<Integer>();
  numbers.add(new Integer(2));
  numbers.add(new Integer(4));
  numbers.add(new Integer(5));
  int total = product(numbers);
  System.out.println(total);
}

public static int product(ArrayList<Integer> nums) {
  int product = 1;
  for (int i = 0; i < nums.size(); i++) {
    Integer n = nums.get(i); //no cast; returns Integer now
    product *= n.intValue();
  }
  return product;
}

Very modern ArrayList use

Autoboxing, for-each loop

public static void main(String[] args) {
  ArrayList<Integer> numbers = new ArrayList<Integer>();
  numbers.add(2);
  numbers.add(4);
  numbers.add(5);
  int total = product(numbers);
  System.out.println(total);
}

public static int product(ArrayList<Integer> nums) {
  int product = 1;
  for (int n : nums) {
    product *= n;
  }
  return product;
}

Old way: Implement Queue

Still general purpose: Can insert any kind of object

class Queue {  //no <E>

  private static final int CAPACITY = 5;

  private Object[] items;
  private int front;  //points at first item
  private int back;   //first blank spot

  public Queue() {
    Object[] array = new Object[CAPACITY + 1];
    items = array;
    back = 0;
    front = 0;
  }

  public void offer(Object item) {
    if (this.size() == CAPACITY) {
      //Implementation-level restriction: would be nice to avoid this...
      throw new IllegalStateException("Queue is full.");
    }
    this.items[back] = item;
    this.back = (this.back + 1) % items.length;
  }

  public Object peek() {
    if (this.size() == 0) {
      throw new IllegalStateException("Queue is empty.");
    }
    return this.items[front];
  }

  public Object poll() {
    Object item = this.peek();  //throws exception if empty
    this.front = (this.front + 1) % items.length;
    return item;
  }

  public int size() {
    return (this.back + items.length - this.front) % items.length;
  }
}

Old way: Using Queue

  public static void main(String[] args) {
    Queue q = new Queue();
    q.offer("here");
    q.offer("there");
    q.offer(4.3);  //autoboxed -> Integer -> Object

    //...

    while (q.size() > 0) {
      Object o = q.poll();              //every thing comes out as Object
      String str = (String) o;          //need to cast back to what you put in
      System.out.println(str.length());  //crash: ClassCastException
    }
  }

Type Erasure

Generic array creation

class Queue<E> {

  private static final int CAPACITY = 5;

  private E[] items;
  private int front;  
  private int back; 

  public Queue() {
    this.items = new E[CAPACITY];  //NO!  Does not compile
    this.front = 0;
    this.back = 0;
  }
}

Compiler can't put a specific E here: Integer, String, what? Needs one type that works for all Stack uses.

Generic array creation

  this.items = new E[CAPACITY];  //NO!  Does not compile

  this.items = new Object[CAPACITY];  //NO!  E[] != Object[]

  this.items = (E[]) new Object[CAPACITY];  //Works... but warning
    @SuppressWarnings("unchecked")
    E[] array = (E[]) new Object[CAPACITY];
    this.items = array;

Arrays of parametized types

Conclusions

More info: Java Tutorial, Arrays in Java Generics

BTW: Good Java references

If you want to master the more advanced aspects of Java, I enjoyed:

Can access digital versions of both for free through UH Library, but only 4 users at a time.

Method call series

Given:

ArrayList<PyramidStack<Meep>> shafts = new ArrayList<PyramidStack<Meep>>();
//... add three new PyramidStack<Meep>()s
Meep newcomer = new Meep(5);  //Meeps are Comparable, so has compareTo method.

Problem: See if meep on top of left shaft (index: 0) is smaller than newcomer

   (shafts)                  //whole ArrayList
   (shafts.get(0))           //first PyramidStack<Meep>
   (shafts.get(0).peek())    //Top of that stack: a Meep
   (shafts.get(0).peek().compareTo(newcomer))   //an int
  if (shafts.get(0).peek().compareTo(newcomer) < 0) {
    //top meep is smaller

Shortcut logic operators

  if (shafts.get(0).peek().compareTo(newcomer) < 0) {
    //top meep is smaller

Now we have 3 stacks in shafts, but what if stack at shaft.get(0) is empty? Crash!

  if (shafts.get(0).size() > 0 && 
      shafts.get(0).peek().compareTo(newcomer) < 0) {
    //...
  if (shafts.get(0).size() == 0 ||
      shafts.get(0).peek().compareTo(newcomer) < 0) {
    //newcomer can move to first shaft

For next time...