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 18 package java.util; 19 20 import java.lang.reflect.Array; 21 22 /** 23 * Class {@code AbstractCollection} is an abstract implementation of the {@code 24 * Collection} interface. A subclass must implement the abstract methods {@code 25 * iterator()} and {@code size()} to create an immutable collection. To create a 26 * modifiable collection it's necessary to override the {@code add()} method that 27 * currently throws an {@code UnsupportedOperationException}. 28 * 29 * @since 1.2 30 */ 31 public abstract class AbstractCollection<E> implements Collection<E> { 32 33 /** 34 * Constructs a new instance of this AbstractCollection. 35 */ AbstractCollection()36 protected AbstractCollection() { 37 } 38 add(E object)39 public boolean add(E object) { 40 throw new UnsupportedOperationException(); 41 } 42 43 /** 44 * Attempts to add all of the objects contained in {@code collection} 45 * to the contents of this {@code Collection} (optional). This implementation 46 * iterates over the given {@code Collection} and calls {@code add} for each 47 * element. If any of these calls return {@code true}, then {@code true} is 48 * returned as result of this method call, {@code false} otherwise. If this 49 * {@code Collection} does not support adding elements, an {@code 50 * UnsupportedOperationException} is thrown. 51 * <p> 52 * If the passed {@code Collection} is changed during the process of adding elements 53 * to this {@code Collection}, the behavior depends on the behavior of the passed 54 * {@code Collection}. 55 * 56 * @param collection 57 * the collection of objects. 58 * @return {@code true} if this {@code Collection} is modified, {@code false} 59 * otherwise. 60 * @throws UnsupportedOperationException 61 * if adding to this {@code Collection} is not supported. 62 * @throws ClassCastException 63 * if the class of an object is inappropriate for this 64 * {@code Collection}. 65 * @throws IllegalArgumentException 66 * if an object cannot be added to this {@code Collection}. 67 * @throws NullPointerException 68 * if {@code collection} is {@code null}, or if it contains 69 * {@code null} elements and this {@code Collection} does not support 70 * such elements. 71 */ addAll(Collection<? extends E> collection)72 public boolean addAll(Collection<? extends E> collection) { 73 boolean result = false; 74 Iterator<? extends E> it = collection.iterator(); 75 while (it.hasNext()) { 76 if (add(it.next())) { 77 result = true; 78 } 79 } 80 return result; 81 } 82 83 /** 84 * Removes all elements from this {@code Collection}, leaving it empty (optional). 85 * This implementation iterates over this {@code Collection} and calls the {@code 86 * remove} method on each element. If the iterator does not support removal 87 * of elements, an {@code UnsupportedOperationException} is thrown. 88 * <p> 89 * Concrete implementations usually can clear a {@code Collection} more efficiently 90 * and should therefore overwrite this method. 91 * 92 * @throws UnsupportedOperationException 93 * it the iterator does not support removing elements from 94 * this {@code Collection} 95 * @see #iterator 96 * @see #isEmpty 97 * @see #size 98 */ clear()99 public void clear() { 100 Iterator<E> it = iterator(); 101 while (it.hasNext()) { 102 it.next(); 103 it.remove(); 104 } 105 } 106 107 /** 108 * Tests whether this {@code Collection} contains the specified object. This 109 * implementation iterates over this {@code Collection} and tests, whether any 110 * element is equal to the given object. If {@code object != null} then 111 * {@code object.equals(e)} is called for each element {@code e} returned by 112 * the iterator until the element is found. If {@code object == null} then 113 * each element {@code e} returned by the iterator is compared with the test 114 * {@code e == null}. 115 * 116 * @param object 117 * the object to search for. 118 * @return {@code true} if object is an element of this {@code Collection}, {@code 119 * false} otherwise. 120 * @throws ClassCastException 121 * if the object to look for isn't of the correct type. 122 * @throws NullPointerException 123 * if the object to look for is {@code null} and this 124 * {@code Collection} doesn't support {@code null} elements. 125 */ contains(Object object)126 public boolean contains(Object object) { 127 Iterator<E> it = iterator(); 128 if (object != null) { 129 while (it.hasNext()) { 130 if (object.equals(it.next())) { 131 return true; 132 } 133 } 134 } else { 135 while (it.hasNext()) { 136 if (it.next() == null) { 137 return true; 138 } 139 } 140 } 141 return false; 142 } 143 144 /** 145 * Tests whether this {@code Collection} contains all objects contained in the 146 * specified {@code Collection}. This implementation iterates over the specified 147 * {@code Collection}. If one element returned by the iterator is not contained in 148 * this {@code Collection}, then {@code false} is returned; {@code true} otherwise. 149 * 150 * @param collection 151 * the collection of objects. 152 * @return {@code true} if all objects in the specified {@code Collection} are 153 * elements of this {@code Collection}, {@code false} otherwise. 154 * @throws ClassCastException 155 * if one or more elements of {@code collection} isn't of the 156 * correct type. 157 * @throws NullPointerException 158 * if {@code collection} contains at least one {@code null} 159 * element and this {@code Collection} doesn't support {@code null} 160 * elements. 161 * @throws NullPointerException 162 * if {@code collection} is {@code null}. 163 */ containsAll(Collection<?> collection)164 public boolean containsAll(Collection<?> collection) { 165 Iterator<?> it = collection.iterator(); 166 while (it.hasNext()) { 167 if (!contains(it.next())) { 168 return false; 169 } 170 } 171 return true; 172 } 173 174 /** 175 * Returns if this {@code Collection} contains no elements. This implementation 176 * tests, whether {@code size} returns 0. 177 * 178 * @return {@code true} if this {@code Collection} has no elements, {@code false} 179 * otherwise. 180 * 181 * @see #size 182 */ isEmpty()183 public boolean isEmpty() { 184 return size() == 0; 185 } 186 187 /** 188 * Returns an instance of {@link Iterator} that may be used to access the 189 * objects contained by this {@code Collection}. The order in which the elements are 190 * returned by the {@link Iterator} is not defined unless the instance of the 191 * {@code Collection} has a defined order. In that case, the elements are returned in that order. 192 * <p> 193 * In this class this method is declared abstract and has to be implemented 194 * by concrete {@code Collection} implementations. 195 * 196 * @return an iterator for accessing the {@code Collection} contents. 197 */ iterator()198 public abstract Iterator<E> iterator(); 199 200 /** 201 * Removes one instance of the specified object from this {@code Collection} if one 202 * is contained (optional). This implementation iterates over this 203 * {@code Collection} and tests for each element {@code e} returned by the iterator, 204 * whether {@code e} is equal to the given object. If {@code object != null} 205 * then this test is performed using {@code object.equals(e)}, otherwise 206 * using {@code object == null}. If an element equal to the given object is 207 * found, then the {@code remove} method is called on the iterator and 208 * {@code true} is returned, {@code false} otherwise. If the iterator does 209 * not support removing elements, an {@code UnsupportedOperationException} 210 * is thrown. 211 * 212 * @param object 213 * the object to remove. 214 * @return {@code true} if this {@code Collection} is modified, {@code false} 215 * otherwise. 216 * @throws UnsupportedOperationException 217 * if removing from this {@code Collection} is not supported. 218 * @throws ClassCastException 219 * if the object passed is not of the correct type. 220 * @throws NullPointerException 221 * if {@code object} is {@code null} and this {@code Collection} 222 * doesn't support {@code null} elements. 223 */ remove(Object object)224 public boolean remove(Object object) { 225 Iterator<?> it = iterator(); 226 if (object != null) { 227 while (it.hasNext()) { 228 if (object.equals(it.next())) { 229 it.remove(); 230 return true; 231 } 232 } 233 } else { 234 while (it.hasNext()) { 235 if (it.next() == null) { 236 it.remove(); 237 return true; 238 } 239 } 240 } 241 return false; 242 } 243 244 /** 245 * Removes all occurrences in this {@code Collection} of each object in the 246 * specified {@code Collection} (optional). After this method returns none of the 247 * elements in the passed {@code Collection} can be found in this {@code Collection} 248 * anymore. 249 * <p> 250 * This implementation iterates over this {@code Collection} and tests for each 251 * element {@code e} returned by the iterator, whether it is contained in 252 * the specified {@code Collection}. If this test is positive, then the {@code 253 * remove} method is called on the iterator. If the iterator does not 254 * support removing elements, an {@code UnsupportedOperationException} is 255 * thrown. 256 * 257 * @param collection 258 * the collection of objects to remove. 259 * @return {@code true} if this {@code Collection} is modified, {@code false} 260 * otherwise. 261 * @throws UnsupportedOperationException 262 * if removing from this {@code Collection} is not supported. 263 * @throws ClassCastException 264 * if one or more elements of {@code collection} isn't of the 265 * correct type. 266 * @throws NullPointerException 267 * if {@code collection} contains at least one {@code null} 268 * element and this {@code Collection} doesn't support {@code null} 269 * elements. 270 * @throws NullPointerException 271 * if {@code collection} is {@code null}. 272 */ removeAll(Collection<?> collection)273 public boolean removeAll(Collection<?> collection) { 274 boolean result = false; 275 Iterator<?> it = iterator(); 276 while (it.hasNext()) { 277 if (collection.contains(it.next())) { 278 it.remove(); 279 result = true; 280 } 281 } 282 return result; 283 } 284 285 /** 286 * Removes all objects from this {@code Collection} that are not also found in the 287 * {@code Collection} passed (optional). After this method returns this {@code Collection} 288 * will only contain elements that also can be found in the {@code Collection} 289 * passed to this method. 290 * <p> 291 * This implementation iterates over this {@code Collection} and tests for each 292 * element {@code e} returned by the iterator, whether it is contained in 293 * the specified {@code Collection}. If this test is negative, then the {@code 294 * remove} method is called on the iterator. If the iterator does not 295 * support removing elements, an {@code UnsupportedOperationException} is 296 * thrown. 297 * 298 * @param collection 299 * the collection of objects to retain. 300 * @return {@code true} if this {@code Collection} is modified, {@code false} 301 * otherwise. 302 * @throws UnsupportedOperationException 303 * if removing from this {@code Collection} is not supported. 304 * @throws ClassCastException 305 * if one or more elements of {@code collection} 306 * isn't of the correct type. 307 * @throws NullPointerException 308 * if {@code collection} contains at least one 309 * {@code null} element and this {@code Collection} doesn't support 310 * {@code null} elements. 311 * @throws NullPointerException 312 * if {@code collection} is {@code null}. 313 */ retainAll(Collection<?> collection)314 public boolean retainAll(Collection<?> collection) { 315 boolean result = false; 316 Iterator<?> it = iterator(); 317 while (it.hasNext()) { 318 if (!collection.contains(it.next())) { 319 it.remove(); 320 result = true; 321 } 322 } 323 return result; 324 } 325 326 /** 327 * Returns a count of how many objects this {@code Collection} contains. 328 * <p> 329 * In this class this method is declared abstract and has to be implemented 330 * by concrete {@code Collection} implementations. 331 * 332 * @return how many objects this {@code Collection} contains, or {@code Integer.MAX_VALUE} 333 * if there are more than {@code Integer.MAX_VALUE} elements in this 334 * {@code Collection}. 335 */ size()336 public abstract int size(); 337 toArray()338 public Object[] toArray() { 339 return toArrayList().toArray(); 340 } 341 toArray(T[] contents)342 public <T> T[] toArray(T[] contents) { 343 return toArrayList().toArray(contents); 344 } 345 346 @SuppressWarnings("unchecked") toArrayList()347 private ArrayList<Object> toArrayList() { 348 ArrayList<Object> result = new ArrayList<Object>(size()); 349 for (E entry : this) { 350 result.add(entry); 351 } 352 return result; 353 } 354 355 /** 356 * Returns the string representation of this {@code Collection}. The presentation 357 * has a specific format. It is enclosed by square brackets ("[]"). Elements 358 * are separated by ', ' (comma and space). 359 * 360 * @return the string representation of this {@code Collection}. 361 */ 362 @Override toString()363 public String toString() { 364 if (isEmpty()) { 365 return "[]"; 366 } 367 368 StringBuilder buffer = new StringBuilder(size() * 16); 369 buffer.append('['); 370 Iterator<?> it = iterator(); 371 while (it.hasNext()) { 372 Object next = it.next(); 373 if (next != this) { 374 buffer.append(next); 375 } else { 376 buffer.append("(this Collection)"); 377 } 378 if (it.hasNext()) { 379 buffer.append(", "); 380 } 381 } 382 buffer.append(']'); 383 return buffer.toString(); 384 } 385 } 386