import java.util.ArrayList; import java.util.Iterator; import java.util.Random; /** Let's implement a bag using an ArrayList. Some operations are rather * straightforward because an ArrayList already has certain operations * built-in. This bag class needs a base type, so let's just say it's * a bag of Item objects. We'll assume that Item class has its own equals() * and toString(). * Even though we're specifying the representation and other implementation * details of a bag, we don't specify what the bag is useful for -- we just * know it contains an ArrayList of objects. If you have a specific kind * of object in mind... this is why I have a specific "Item" class, which is * defined elsewhere. So this class can be used for a variety of programs * without modification. Each new application just needs an Item class * and an ItemComparator class. * So far, the only reason why we need an "Item" class is so that when we * want to remove a specific element, we can call the appropriate equals(). */ public class BagArrayList implements BagInterface { private ArrayList list; // Although the interface didn't say so, we really need // a constructor. public BagArrayList() { list = new ArrayList(); } public void add(Object o) { list.add((Item) o); } // This remove() function, that takes no parameter, is supposed to // remove a random element from the bag. So we need to pick a random // number, and then call the ArrayList remove function. public Item remove() { Random gen = new Random(); int index = gen.nextInt(list.size()); return list.remove(index); } // The ArrayList remove function needs to know the index, so we have // to find it in the bag first. This adds complexity to the operation. // It will be linear instead of constant time. public Item remove(Object o) { Item i = (Item) o; int index = indexOf(i); if (index == -1) return null; else return list.remove(indexOf(i)); } // This function is private because only here do we care that // the underlying implementation is an ArrayList. // As in the String indexOf, we'll return -1 if not found. // For this function to work, we need some way of determining // if two objects are equal. private int indexOf(Item item) { for (int i = 0; i < list.size(); ++i) if (list.get(i).equals(item)) return i; return -1; } // To combine means to create a new bag and put into it the combined // contents of my bag and some other bag. The original 2 bags are unchanged. public BagInterface combine(BagInterface b) { BagArrayList newBag = new BagArrayList(); for (int i = 0; i < this.size(); ++i) newBag.add(list.get(i)); for (int i = 0; i < ((BagArrayList) b).size(); ++i) newBag.add(((BagArrayList) b).list.get(i)); return newBag; } // Need to sort the bags and then compare them by corresponding elements // one by one until we see a pair that doesn't match or we've seen them all. public boolean equals(BagInterface b) { if (this.size() != b.size()) return false; // Would be nice to sort the 2 bags, so the order of their // elements does not matter when we compare them. // sort(); // ((BagArrayList) b).sort(); for (int i = 0; i < list.size(); ++i) if (! list.get(i).equals(((BagArrayList) b).list.get(i))) return false; return true; } public void give(Object o, BagInterface b) { Item i = (Item) o; this.remove(i); b.add(i); } public int size() { return list.size(); } public String toString() { StringBuilder build = new StringBuilder(); for (int i = 0; i < list.size(); ++i) build.append("\t" + list.get(i) + "\n"); return build.toString(); } // The ArrayList class already has an iterator, but let's have // some practice writing one of our own. class BagIterator implements Iterator { int currentIndex; public BagIterator() { currentIndex = 0; } public boolean hasNext() { return currentIndex < list.size(); } public Object next() { return list.get(currentIndex++); } // According to the API documentation on Iterator's remove(), we // need to remove the element that "next" just returned. // However, I don't think this type of removal will be useful for // our application, so I'll leave it unimplemented. public void remove() { throw new UnsupportedOperationException(); } } public Iterator bagIterator() { return new BagIterator(); } }