import java.util.*; interface ItemChooser<T> { T getNext(); T getSentinel(); int size(); void reset(); } abstract class AbstractItemChooser<T> implements ItemChooser<T> { private T sentinel; private T[] items; private List<T> available; protected AbstractItemChooser(T[] items, T sentinelValue) { this.items = items; this.sentinel = sentinel; available = new ArrayList<T>(items.length); reset(); } public T getNext() { return available.size() > 0 ? available.remove(getIndexOfNext()) : sentinel; } public T getSentinel() { return sentinel; } public int size() { return available.size(); } public void reset() { available.clear(); for (int i = 0; i < items.length; i++) { available.add(items[i]); } } protected abstract int getIndexOfNext(); } class RandomItemChooser<T> extends AbstractItemChooser<T> { public RandomItemChooser(T[] items, T sentinel) { super(items, sentinel); } protected int getIndexOfNext() { return (int)(Math.random() * size()); } } class RandomStringChooser extends RandomItemChooser<String> { public RandomStringChooser(String[] strings) { super(strings, "NONE"); } } public class Items { public static <T> void process(ItemChooser<T> chooser) { while (chooser.size() > 0) { System.out.print(chooser.getNext() + " "); } System.out.println(); } public static void main(String args[]) { ItemChooser<String> randomChooser, sequentialChooser, reverseChooser; randomChooser = new RandomStringChooser(args); process(randomChooser); //process(sequentialChooser); //process(reverseChooser); } }