1: import java.util.Arrays;
2: /**
3: A class that implements a bag of objects by using an array.
4: The bag is never full.
5: @author Frank M. Carrano
6: @version 4.0
7: */
8: public final class ResizableArrayBag<T> implements BagInterface<T>
9: {
10: private T[] bag; // Cannot be final due to doubling
11: private int numberOfEntries;
12: private boolean initialized = false;
13: private static final int DEFAULT_CAPACITY = 25; // Initial capacity of bag
14: private static final int MAX_CAPACITY = 10000;
15:
16: /** Creates an empty bag whose initial capacity is 25. */
17: public ResizableArrayBag()
18: {
19: this(DEFAULT_CAPACITY);
20: } // end default constructor
21:
22: /** Creates an empty bag having a given initial capacity.
23: @param initialCapacity The integer capacity desired. */
24: public ResizableArrayBag(int initialCapacity)
25: {
26: checkCapacity(initialCapacity);
27:
28: // The cast is safe because the new array contains null entries
29: @SuppressWarnings("unchecked")
30: T[] tempBag = (T[])new Object[initialCapacity]; // Unchecked cast
31: bag = tempBag;
32: numberOfEntries = 0;
33: initialized = true;
34: } // end constructor
35:
36: /** Creates a bag containing given entries.
37: @param contents An array of objects. */
38: public ResizableArrayBag(T[] contents)
39: {
40: checkCapacity(contents.length);
41: bag = Arrays.copyOf(contents, contents.length);
42: numberOfEntries = contents.length;
43: initialized = true;
44: } // end constructor
45:
46: /** Adds a new entry to this bag.
47: @param newEntry The object to be added as a new entry.
48: @return True. */
49: public boolean add(T newEntry)
50: {
51: checkInitialization();
52: if (isArrayFull())
53: {
54: doubleCapacity();
55: } // end if
56:
57: bag[numberOfEntries] = newEntry;
58: numberOfEntries++;
59:
60: return true;
61: } // end add
62:
63: /** Retrieves all entries that are in this bag.
64: @return A newly allocated array of all the entries in this bag. */
65: public T[] toArray()
66: {
67: checkInitialization();
68:
69: // The cast is safe because the new array contains null entries.
70: @SuppressWarnings("unchecked")
71: T[] result = (T[])new Object[numberOfEntries]; // Unchecked cast
72: for (int index = 0; index < numberOfEntries; index++)
73: {
74: result[index] = bag[index];
75: } // end for
76:
77: return result;
78: } // end toArray
79:
80: /** Sees whether this bag is empty.
81: @return True if this bag is empty, or false if not. */
82: public boolean isEmpty()
83: {
84: return numberOfEntries == 0;
85: } // end isEmpty
86:
87: /** Gets the current number of entries in this bag.
88: @return The integer number of entries currently in this bag. */
89: public int getCurrentSize()
90: {
91: return numberOfEntries;
92: } // end getCurrentSize
93:
94: /** Counts the number of times a given entry appears in this bag.
95: @param anEntry The entry to be counted.
96: @return The number of times anEntry appears in this ba. */
97: public int getFrequencyOf(T anEntry)
98: {
99: checkInitialization();
100: int counter = 0;
101:
102: for (int index = 0; index < numberOfEntries; index++)
103: {
104: if (anEntry.equals(bag[index]))
105: {
106: counter++;
107: } // end if
108: } // end for
109:
110: return counter;
111: } // end getFrequencyOf
112:
113: /** Tests whether this bag contains a given entry.
114: @param anEntry The entry to locate.
115: @return True if this bag contains anEntry, or false otherwise. */
116: public boolean contains(T anEntry)
117: {
118: checkInitialization();
119: return getIndexOf(anEntry) > -1; // or >= 0
120: } // end contains
121:
122: /** Removes all entries from this bag. */
123: public void clear()
124: {
125: while (!isEmpty())
126: remove();
127: } // end clear
128:
129: /** Removes one unspecified entry from this bag, if possible.
130: @return Either the removed entry, if the removal
131: was successful, or null. */
132: public T remove()
133: {
134: checkInitialization();
135: T result = removeEntry(numberOfEntries - 1);
136: return result;
137: } // end remove
138:
139: /** Removes one occurrence of a given entry from this bag.
140: @param anEntry The entry to be removed.
141: @return True if the removal was successful, or false if not. */
142: public boolean remove(T anEntry)
143: {
144: checkInitialization();
145: int index = getIndexOf(anEntry);
146: T result = removeEntry(index);
147: return anEntry.equals(result);
148: } // end remove
149:
150: // Locates a given entry within the array bag.
151: // Returns the index of the entry, if located,
152: // or -1 otherwise.
153: // Precondition: checkInitialization has been called.
154: private int getIndexOf(T anEntry)
155: {
156: int where = -1;
157: boolean found = false;
158: int index = 0;
159:
160: while (!found && (index < numberOfEntries))
161: {
162: if (anEntry.equals(bag[index]))
163: {
164: found = true;
165: where = index;
166: } // end if
167: index++;
168: } // end while
169:
170: // Assertion: If where > -1, anEntry is in the array bag, and it
171: // equals bag[where]; otherwise, anEntry is not in the array.
172:
173: return where;
174: } // end getIndexOf
175:
176: // Removes and returns the entry at a given index within the array.
177: // If no such entry exists, returns null.
178: // Precondition: 0 <= givenIndex < numberOfEntries.
179: // Precondition: checkInitialization has been called.
180: private T removeEntry(int givenIndex)
181: {
182: T result = null;
183:
184: if (!isEmpty() && (givenIndex >= 0))
185: {
186: result = bag[givenIndex]; // Entry to remove
187: int lastIndex = numberOfEntries - 1;
188: bag[givenIndex] = bag[lastIndex]; // Replace entry to remove with last entry
189: bag[lastIndex] = null; // Remove reference to last entry
190: numberOfEntries--;
191: } // end if
192:
193: return result;
194: } // end removeEntry
195:
196: // Returns true if the array bag is full, or false if not.
197: private boolean isArrayFull()
198: {
199: return numberOfEntries >= bag.length;
200: } // end isArrayFull
201:
202: // Doubles the size of the array bag.
203: // Precondition: checkInitialization has been called.
204: private void doubleCapacity()
205: {
206: int newLength = 2 * bag.length;
207: checkCapacity(newLength);
208: bag = Arrays.copyOf(bag, newLength);
209: } // end doubleCapacity
210:
211: // Throws an exception if the client requests a capacity that is too large.
212: private void checkCapacity(int capacity)
213: {
214: if (capacity > MAX_CAPACITY)
215: throw new IllegalStateException("Attempt to create a bag whose capacity exceeds " +
216: "allowed maximum of " + MAX_CAPACITY);
217: } // end checkCapacity
218:
219: // Throws an exception if receiving object is not initialized.
220: private void checkInitialization()
221: {
222: if (!initialized)
223: throw new SecurityException ("Uninitialized object used " +
224: "to call an ArrayBag method.");
225: } // end checkInitialization
226: } // end ResizableArrayBag
227:
228:
229: