Source of FixedSizeArrayBag.java


  1: /** FixedSizeArrayBag.java
  2:     A class of bags whose entries are stored in a fixed-size array.
  3:     @author Frank M. Carrano
  4:     @version 4.0
  5: */
  6: public final class FixedSizeArrayBag<T> implements BagInterface<T>
  7: {
  8:     private final T[] bag;
  9:     private int numberOfEntries;
 10:     private boolean initialized = false;
 11:     private static final int DEFAULT_CAPACITY = 25;
 12:     private static final int MAX_CAPACITY = 10000;

 14:     //********************************************************************
 15:     //This section contains two constructors and two public core methods.
 16:     //********************************************************************
 17:     /**
 18:         Create an empty bag whose initial capacity is 25.
 19:     */
 20:     public FixedSizeArrayBag()
 21:     {
 22:         this(DEFAULT_CAPACITY);
 23:     }

 25:     /**
 26:         Create an empty bag having a given capacity.
 27:         @param desiredCapacity The integer capacity desired.
 28:     */
 29:     public FixedSizeArrayBag(int desiredCapacity)
 30:     {
 31:         if (desiredCapacity <= MAX_CAPACITY)
 32:         {
 33:             //Notes:
 34:             //1. bag = new T[desiredCapacity]; //syntax error
 35:             //   Cannot create array of generic type
 36:             //2. bag = new Object[desiredCapacity]; //syntax error
 37:             //   Incompatible types
 38:             //3. bag = (T[]) new Object[desiredCapacity];
 39:             //   Gives a compiler warning about an "unchecked cast"
 40:             //We can tell the compiler that the cast is safe because the new
 41:             //array contains null entries, which we do with the following
 42:             //annotation:
 43:             @SuppressWarnings("unchecked")
 44:             //But this annotation can only be placed in front of a method
 45:             //definition or a variable declaration, and since bag has already
 46:             //been declared we have to do this:
 47:             T[] tempBag = (T[]) new Object[desiredCapacity]; //Unchecked cast
 48:             bag = tempBag;
 49:             numberOfEntries = 0;
 50:             initialized = true;
 51:         }
 52:         else
 53:         {
 54:             throw new IllegalStateException
 55:             (
 56:                 "Attempt to create a bag "
 57:                 + "whose capacity exceeds allowed maximum."
 58:             );
 59:         }
 60:     }

 62:     /**
 63:         Add a new entry to this bag.
 64:         @param newEntry The object to be added as a new entry.
 65:         @return true if the addition is successful, or false if not.
 66:     */
 67:     public boolean add(T newEntry)
 68:     {
 69:         checkInitialization();
 70:         boolean result = true;
 71:         if (isArrayFull())
 72:         {
 73:             result = false;
 74:         }
 75:         else
 76:         {
 77:             //Assertion: result is true here
 78:             bag[numberOfEntries] = newEntry;
 79:             numberOfEntries++;
 80:         }
 81:         return result;
 82:     }

 84:     /**
 85:         Retrieve all entries that are in this bag and put them into an array.
 86:         @return A newly allocated array of all the entries in this bag.
 87:     */
 88:     //public <T> T[] toArray() //Also OK
 89:     public T[] toArray()
 90:     {
 91:         checkInitialization();

 93:         //The cast is safe because the new array contains null entries.
 94:         @SuppressWarnings("unchecked")
 95:         T[] result = (T[]) new Object[numberOfEntries]; // Unchecked cast

 97:         for (int index = 0; index < numberOfEntries; index++)
 98:         {
 99:             result[index] = bag[index];
100:         }
101:         return result;
102:         //Note that we could have made the body of this method
103:         //much shorter by using the Arrays.copyOf() method.
104:     }

106:     //********************************************************************
107:     //This section contains seven additional public methods.
108:     //********************************************************************
109:     /**
110:         Test whether this bag is empty.
111:         @return True if this bag is empty, or false if not.
112:     */
113:     public boolean isEmpty()
114:     {
115:         return numberOfEntries == 0;
116:     }

118:     /**
119:         Get the current number of entries in this bag.
120:         @return The integer number of entries currently in this bag.
121:     */
122:     public int getCurrentSize()
123:     {
124:         return numberOfEntries;
125:     }

127:     /**
128:         Count the number of times a given entry appears in this bag.
129:         @param anEntry The entry to be counted.
130:         @return The number of times anEntry appears in this bag.
131:     */
132:     public int getFrequencyOf(T anEntry)
133:     {
134:         checkInitialization();
135:         int counter = 0;
136:         for (int index = 0; index < numberOfEntries; index++)
137:         {
138:             if (anEntry.equals(bag[index]))
139:             {
140:                 counter++;
141:             }
142:         }
143:         return counter;
144:     }

146:     /**
147:         Test whether this bag contains a given entry.
148:         @param anEntry The entry to locate.
149:         @return true if this bag contains anEntry, or false otherwise.
150:     */
151:     public boolean contains(T anEntry)
152:     {
153:         checkInitialization();
154:         return getIndexOf(anEntry) > -1; // or >= 0
155:     }

157:     /**
158:         Remove all entries from this bag.
159:     */
160:     public void clear()
161:     {
162:         while (!isEmpty())
163:         {
164:             remove();
165:         }
166:     }

168:     /**
169:         Remove one unspecified entry from this bag, if possible.
170:         @return Either the removed entry, if removal was successful, or null.
171:     */
172:     public T remove()
173:     {
174:         checkInitialization();
175:         T result = removeEntry(numberOfEntries - 1);
176:         return result;
177:     }

179:     /**
180:         Remove one occurrence of a given entry from this bag.
181:         @param anEntry The entry to be removed.
182:         @return true if the removal was successful, or false if not.
183:     */
184:     public boolean remove(T anEntry)
185:     {
186:         checkInitialization();
187:         int index = getIndexOf(anEntry);
188:         T result = removeEntry(index);
189:         return anEntry.equals(result);
190:     }

192:     //********************************************************************
193:     //This section contains four private helper methods.
194:     //********************************************************************
195:     //Return true if the array bag is full, or false if not.
196:     private boolean isArrayFull()
197:     {
198:         return numberOfEntries >= bag.length;
199:     }

201:     //Locate a given entry within the array bag.
202:     //Return the index of the entry if located, -1 otherwise.
203:     //Pre-condition: checkInitialization() has been called.
204:     private int getIndexOf(T anEntry)
205:     {
206:         int where = -1;
207:         boolean found = false;
208:         int index = 0;
209:         while (!found && (index < numberOfEntries))
210:         {
211:             if (anEntry.equals(bag[index]))
212:             {
213:                 found = true;
214:                 where = index;
215:             }
216:             index++;
217:         }
218:         //Assertion: If where > -1, anEntry is in the array bag, and it
219:         //equals bag[where]; otherwise, anEntry is not in the array.

221:         return where;
222:     }

224:     //Remove and return the entry at a given index within the array.
225:     //If no such entry exists, return null.
226:     //Pre-condition: 0 <= givenIndex < numberOfEntries.
227:     //Pre-condition: checkInitialization() has been called.
228:     private T removeEntry(int givenIndex)
229:     {
230:         T result = null;

232:         if (!isEmpty() && (givenIndex >= 0))
233:         {
234:             result = bag[givenIndex]; //Entry to remove
235:             int lastIndex = numberOfEntries - 1;

237:             //Replace entry to remove with last entry, then
238:             //remove reference to last entry and adjust numberOfEntries.
239:             bag[givenIndex] = bag[lastIndex];
240:             bag[lastIndex] = null;
241:             numberOfEntries--;
242:         }
243:         return result;
244:     }

246:     //Throw an exception if this object is not initialized.
247:     private void checkInitialization()
248:     {
249:         if (!initialized)
250:         {
251:             throw new SecurityException
252:             (
253:                 "FixedSizeArrayBag object is not "
254:                 + "initialized properly."
255:             );
256:         }
257:     }
258: }