AbstractCollection.java revision 2ad60cfc28e14ee8f0bb038720836a4696c478ad
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.util; 19 20 21import java.lang.reflect.Array; 22 23/** 24 * AbstractCollection is an abstract implementation of the Collection interface. 25 * This implementation does not support adding. A subclass must implement the 26 * abstract methods iterator() and size(). 27 * @since 1.2 28 */ 29public abstract class AbstractCollection<E> implements Collection<E> { 30 31 /** 32 * Constructs a new instance of this AbstractCollection. 33 */ 34 protected AbstractCollection() { 35 super(); 36 } 37 38 /** 39 * If the specified element is not contained within this collection, and 40 * addition of this element succeeds, then true will be returned. If the 41 * specified element is already contained within this collection, or 42 * duplication is not permitted, false will be returned. Different 43 * implementations may add specific limitations on this method to filter 44 * permitted elements. For example, in some implementation, null element may 45 * be denied, and NullPointerException will be thrown out. These limitations 46 * should be explicitly documented by specific collection implementation. 47 * 48 * Add operation is not supported in this implementation, and 49 * UnsupportedOperationException will always be thrown out. 50 * 51 * @param object 52 * the element to be added. 53 * @return true if the collection is changed successfully after invoking 54 * this method. Otherwise, false. 55 * @throws UnsupportedOperationException 56 * if add operation is not supported by this class. 57 * @throws NullPointerException 58 * if null is used to invoke this method, and null is not 59 * permitted by this collection. 60 * @throws ClassCastException 61 * if the class type of the specified element is not 62 * compatible with the permitted class type. 63 * @throws IllegalArgumentException 64 * if limitations of this collection prevent the specified 65 * element from being added 66 */ 67 public boolean add(E object) { 68 throw new UnsupportedOperationException(); 69 } 70 71 /** 72 * Adds the objects in the specified Collection to this Collection. 73 * 74 * @param collection 75 * the Collection of objects 76 * @return true if this Collection is modified, false otherwise 77 * 78 * @throws UnsupportedOperationException 79 * when adding to this Collection is not supported 80 * @throws NullPointerException 81 * if null is used to invoke this method 82 */ 83 public boolean addAll(Collection<? extends E> collection) { 84 boolean result = false; 85 Iterator<? extends E> it = collection.iterator(); 86 while (it.hasNext()) { 87 if (add(it.next())) { 88 result = true; 89 } 90 } 91 return result; 92 } 93 94 /** 95 * Removes all the elements in this collection. This collection will be 96 * cleared up after this operation. The operation iterates over the 97 * collection, removes every element using Iterator.remove method. 98 * 99 * UnsupportedOperationException will be thrown out if the iterator returned 100 * by this collection does not implement the remove method and the collection 101 * is not zero length. 102 * 103 * @throws UnsupportedOperationException 104 * if this operation is not implemented. 105 */ 106 public void clear() { 107 Iterator<E> it = iterator(); 108 while (it.hasNext()) { 109 it.next(); 110 it.remove(); 111 } 112 } 113 114 /** 115 * Searches this Collection for the specified object. 116 * 117 * @param object 118 * the object to search for 119 * @return true if <code>object</code> is an element of this Collection, 120 * false otherwise 121 */ 122 public boolean contains(Object object) { 123 Iterator<E> it = iterator(); 124 if (object != null) { 125 while (it.hasNext()) { 126 if (object.equals(it.next())) { 127 return true; 128 } 129 } 130 } else { 131 while (it.hasNext()) { 132 if (it.next() == null) { 133 return true; 134 } 135 } 136 } 137 return false; 138 } 139 140 /** 141 * Searches this Collection for all objects in the specified Collection. 142 * 143 * @param collection 144 * the Collection of objects 145 * @return true if all objects in the specified Collection are elements of 146 * this Collection, false otherwise 147 * @throws NullPointerException 148 * if null is used to invoke this method 149 */ 150 public boolean containsAll(Collection<?> collection) { 151 Iterator<?> it = collection.iterator(); 152 while (it.hasNext()) { 153 if (!contains(it.next())) { 154 return false; 155 } 156 } 157 return true; 158 } 159 160 /** 161 * Returns true if the collection has no element, otherwise false. 162 * 163 * @return true if the collection has no element. 164 */ 165 public boolean isEmpty() { 166 return size() == 0; 167 } 168 169 /** 170 * Returns an Iterator on the elements of this Collection. A subclass must 171 * implement the abstract methods iterator() and size(). 172 * 173 * @return an Iterator on the elements of this Collection 174 * 175 * @see Iterator 176 */ 177 public abstract Iterator<E> iterator(); 178 179 /** 180 * Removes the first occurrence of the specified object from this 181 * Collection. This operation traverses over the collection, looking 182 * for the specified object. Once the object is found, the object will 183 * be removed from the collection using the iterator's remove method. 184 * 185 * This collection will throw an UnsupportedOperationException if the 186 * iterator returned does not implement remove method, and the specified 187 * object is in this collection. 188 * 189 * @param object 190 * the object to remove 191 * @return true if this Collection is modified, false otherwise 192 * 193 * @throws UnsupportedOperationException 194 * when removing from this Collection is not supported 195 */ 196 public boolean remove(Object object) { 197 Iterator<?> it = iterator(); 198 if (object != null) { 199 while (it.hasNext()) { 200 if (object.equals(it.next())) { 201 it.remove(); 202 return true; 203 } 204 } 205 } else { 206 while (it.hasNext()) { 207 if (it.next() == null) { 208 it.remove(); 209 return true; 210 } 211 } 212 } 213 return false; 214 } 215 216 /** 217 * Removes all occurrences in this Collection of each object in the 218 * specified Collection. This operation traverses over the collection 219 * itself, to verify whether each element is contained in the specified 220 * collection. The object will be removed from the collection itself using 221 * the iterator's remove method if it is contained in the specified 222 * collection. 223 * 224 * This collection will throw an UnsupportedOperationException if the 225 * iterator returned does not implement remove method, and the element 226 * in the specified collection is contained in this collection. 227 * 228 * @param collection 229 * the Collection of objects to remove 230 * @return true if this Collection is modified, false otherwise 231 * 232 * @throws UnsupportedOperationException 233 * when removing from this Collection is not supported 234 * @throws NullPointerException 235 * if null is used to invoke this method 236 */ 237 public boolean removeAll(Collection<?> collection) { 238 boolean result = false; 239 Iterator<?> it = iterator(); 240 while (it.hasNext()) { 241 if (collection.contains(it.next())) { 242 it.remove(); 243 result = true; 244 } 245 } 246 return result; 247 } 248 249 /** 250 * Removes all objects from this Collection that are not contained in the 251 * specified Collection. This operation traverses over the collection 252 * itself, to verify whether any element is contained in the specified 253 * collection. The object will be removed from the collection itself using 254 * the iterator's remove method if it is not contained in the specified 255 * collection. 256 * 257 * This collection will throw an UnsupportedOperationException if the 258 * iterator returned does not implement remove method, and the collection 259 * itself does contain elements which do not exist in the specified collection. 260 * 261 * @param collection 262 * the Collection of objects to retain 263 * @return true if this Collection is modified, false otherwise 264 * 265 * @throws UnsupportedOperationException 266 * when removing from this Collection is not supported 267 * @throws NullPointerException 268 * if null is used to invoke this method 269 */ 270 public boolean retainAll(Collection<?> collection) { 271 boolean result = false; 272 Iterator<?> it = iterator(); 273 while (it.hasNext()) { 274 if (!collection.contains(it.next())) { 275 it.remove(); 276 result = true; 277 } 278 } 279 return result; 280 } 281 282 /** 283 * Returns the number of elements in this Collection. 284 * 285 * @return the number of elements in this Collection 286 */ 287 public abstract int size(); 288 289 /** 290 * Returns a new array containing all elements contained in this Collection. 291 * All the elements in the array will not be referenced by the collection. 292 * The elements in the returned array will be sorted to the same order as 293 * those returned by the iterator of this collection itself if the collection 294 * guarantees the order. 295 * 296 * @return an array of the elements from this Collection 297 */ 298 public Object[] toArray() { 299 int size = size(), index = 0; 300 Iterator<?> it = iterator(); 301 Object[] array = new Object[size]; 302 while (index < size) { 303 array[index++] = it.next(); 304 } 305 return array; 306 } 307 308 /** 309 * Returns an array containing all elements contained in this Collection. If 310 * the specified array is large enough to hold the elements, the specified 311 * array is used, otherwise an array of the same type is created. If the 312 * specified array is used and is larger than this Collection, the array 313 * element following the collection elements is set to null. 314 * 315 * @param contents 316 * the array 317 * @return an array of the elements from this Collection 318 * 319 * @throws ArrayStoreException 320 * when the type of an element in this Collection cannot be 321 * stored in the type of the specified array 322 * @throws NullPointerException 323 * if null is used to invoke this method 324 */ 325 @SuppressWarnings("unchecked") 326 public <T> T[] toArray(T[] contents) { 327 int size = size(), index = 0; 328 if (size > contents.length) { 329 Class<?> ct = contents.getClass().getComponentType(); 330 contents = (T[])Array.newInstance(ct, size); 331 } 332 for (E entry: this) { 333 contents[index++] = (T)entry; 334 } 335 if (index < contents.length) { 336 contents[index] = null; 337 } 338 return contents; 339 } 340 341 /** 342 * Returns the string representation of this Collection. The presentation 343 * has a specific format. It is enclosed by square brackets ("[]"). Elements 344 * are separated by ', ' (comma and space). 345 * 346 * @return the string representation of this Collection 347 */ 348 @Override 349 public String toString() { 350 if (isEmpty()) { 351 return "[]"; //$NON-NLS-1$ 352 } 353 354 StringBuilder buffer = new StringBuilder(size() * 16); 355 buffer.append('['); 356 Iterator<?> it = iterator(); 357 while (it.hasNext()) { 358 Object next = it.next(); 359 if (next != this) { 360 buffer.append(next); 361 } else { 362 buffer.append("(this Collection)"); //$NON-NLS-1$ 363 } 364 if(it.hasNext()) { 365 buffer.append(", "); //$NON-NLS-1$ 366 } 367 } 368 buffer.append(']'); 369 return buffer.toString(); 370 } 371} 372