• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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