Source of ResizableArrayBag.java


  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: