/* * GenericStackTest.java * * Created on June 7, 2004, 2:04 PM */ import java.util.Iterator; /** * * @author cpresser */ //Java of course already has a Stack class, however it makes for an //easy to build/easy to understand example of building a Generic collection //...hopefully public class GenericStackTest<T> implements Iterable<T> { protected int MIN_SIZE = 4; //I'll declare a constant for this, because // some of my students might be watching. //place to store the data private T[] data; private int top; /** Creates a new instance of GenericStackTest */ public GenericStackTest() { /* Since you can't create a new T[] array, we'll just cast an Object[] Incidentally, this generates a compiler warning, but is how Java's own implementation of ArrayList does it. :( groan... The warning indicates that the code is not type safe (i.e. it could cause run time type failures). So it is up to us to write code that ensures only the correct type items are put in the array. Therefore the only way to add items is to use the method push. The data array is private so it cannot be modified by subclasses. */ data = (T[])new Object[MIN_SIZE]; //this is illegal // data = new T[MIN_SIZE]; top = -1; } //If you have to ask about these methods, perhaps you should be doing //a different tutorial. public T pop(){ if(isEmpty()){ //we REALLY should throw an exception here, but we won't add that //detail return null; } T result = data[top]; data[top] = null; top--; return result; } public void push(T item){ if(top == data.length - 1){ //recreate the array (double the length) T[] newData = (T[])new Object[data.length * 2]; for(int i = 0; i < data.length; i++){ newData[i] = data[i]; } data = newData; } top++; data[top] = item; } public boolean isEmpty(){ return top < 0; } //print out a representation of the stack public void dump(){ for(int i = top; i >= 0; i--){ System.out.println(i + ": " + data[i]); } /* * This is a place where the new loop would not be appropriate: * e.g. for(T item: data) {...} * - The new for loop goes from 0..length-1, this example goes * backwards. * - The new for loop would include all items in data not just * the "valid" ones. * - We would need to keep track of an index i in order to print the * line number anyway. * * We could, however, make in iterator and make this class iterable * to use the new loop. See example and iterator class below. */ } //get the capacity of the stack public int capacity(){ return data.length; } //just to be thorough public int size(){ return top + 1; } //allows this class to be used in a foreach styl loop public Iterator<T> iterator(){ //create an iterator return new GenericStackTestIterator(); } //an iterator for this class private class GenericStackTestIterator implements Iterator<T>{ int index; GenericStackTestIterator(){ index = top; } public boolean hasNext(){ return index >= 0; } public T next(){ if(index < 0){ throw new java.util.NoSuchElementException(); } T item = data[index]; index--; return item; } public void remove(){ throw new UnsupportedOperationException( "Remove elements from a stack using pop()"); } } /** * @param args the command line arguments */ public static void main(String[] args) { //create a new one that holds Strings GenericStackTest<String> stack = new GenericStackTest<String>(); System.out.println("Capacity: " + stack.capacity()); stack.push("Item 1"); stack.push("Item 2"); stack.push("Item 3"); stack.push("Item 4"); stack.push("Item 5"); System.out.println("Capacity: " + stack.capacity()); String item = stack.pop(); System.out.println("Pop: " + item); System.out.println("Pop: " + stack.pop()); stack.dump(); System.out.println("-----------------"); //curious that this won't compile for(String s: stack){ System.out.println(s); } } }