• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package java.util;
27 
28 /**
29  * This class provides a skeletal implementation of the <tt>Collection</tt>
30  * interface, to minimize the effort required to implement this interface. <p>
31  *
32  * To implement an unmodifiable collection, the programmer needs only to
33  * extend this class and provide implementations for the <tt>iterator</tt> and
34  * <tt>size</tt> methods.  (The iterator returned by the <tt>iterator</tt>
35  * method must implement <tt>hasNext</tt> and <tt>next</tt>.)<p>
36  *
37  * To implement a modifiable collection, the programmer must additionally
38  * override this class's <tt>add</tt> method (which otherwise throws an
39  * <tt>UnsupportedOperationException</tt>), and the iterator returned by the
40  * <tt>iterator</tt> method must additionally implement its <tt>remove</tt>
41  * method.<p>
42  *
43  * The programmer should generally provide a void (no argument) and
44  * <tt>Collection</tt> constructor, as per the recommendation in the
45  * <tt>Collection</tt> interface specification.<p>
46  *
47  * The documentation for each non-abstract method in this class describes its
48  * implementation in detail.  Each of these methods may be overridden if
49  * the collection being implemented admits a more efficient implementation.<p>
50  *
51  * This class is a member of the
52  * <a href="{@docRoot}openjdk-redirect.html?v=8&path=/technotes/guides/collections/index.html">
53  * Java Collections Framework</a>.
54  *
55  * @author  Josh Bloch
56  * @author  Neal Gafter
57  * @see Collection
58  * @since 1.2
59  */
60 
61 public abstract class AbstractCollection<E> implements Collection<E> {
62     /**
63      * Sole constructor.  (For invocation by subclass constructors, typically
64      * implicit.)
65      */
AbstractCollection()66     protected AbstractCollection() {
67     }
68 
69     // Query Operations
70 
71     /**
72      * Returns an iterator over the elements contained in this collection.
73      *
74      * @return an iterator over the elements contained in this collection
75      */
iterator()76     public abstract Iterator<E> iterator();
77 
size()78     public abstract int size();
79 
80     /**
81      * {@inheritDoc}
82      *
83      * <p>This implementation returns <tt>size() == 0</tt>.
84      */
isEmpty()85     public boolean isEmpty() {
86         return size() == 0;
87     }
88 
89     /**
90      * {@inheritDoc}
91      *
92      * <p>This implementation iterates over the elements in the collection,
93      * checking each element in turn for equality with the specified element.
94      *
95      * @throws ClassCastException   {@inheritDoc}
96      * @throws NullPointerException {@inheritDoc}
97      */
contains(Object o)98     public boolean contains(Object o) {
99         Iterator<E> it = iterator();
100         if (o==null) {
101             while (it.hasNext())
102                 if (it.next()==null)
103                     return true;
104         } else {
105             while (it.hasNext())
106                 if (o.equals(it.next()))
107                     return true;
108         }
109         return false;
110     }
111 
112     /**
113      * {@inheritDoc}
114      *
115      * <p>This implementation returns an array containing all the elements
116      * returned by this collection's iterator, in the same order, stored in
117      * consecutive elements of the array, starting with index {@code 0}.
118      * The length of the returned array is equal to the number of elements
119      * returned by the iterator, even if the size of this collection changes
120      * during iteration, as might happen if the collection permits
121      * concurrent modification during iteration.  The {@code size} method is
122      * called only as an optimization hint; the correct result is returned
123      * even if the iterator returns a different number of elements.
124      *
125      * <p>This method is equivalent to:
126      *
127      *  <pre> {@code
128      * List<E> list = new ArrayList<E>(size());
129      * for (E e : this)
130      *     list.add(e);
131      * return list.toArray();
132      * }</pre>
133      */
toArray()134     public Object[] toArray() {
135         // Estimate size of array; be prepared to see more or fewer elements
136         Object[] r = new Object[size()];
137         Iterator<E> it = iterator();
138         for (int i = 0; i < r.length; i++) {
139             if (! it.hasNext()) // fewer elements than expected
140                 return Arrays.copyOf(r, i);
141             r[i] = it.next();
142         }
143         return it.hasNext() ? finishToArray(r, it) : r;
144     }
145 
146     /**
147      * {@inheritDoc}
148      *
149      * <p>This implementation returns an array containing all the elements
150      * returned by this collection's iterator in the same order, stored in
151      * consecutive elements of the array, starting with index {@code 0}.
152      * If the number of elements returned by the iterator is too large to
153      * fit into the specified array, then the elements are returned in a
154      * newly allocated array with length equal to the number of elements
155      * returned by the iterator, even if the size of this collection
156      * changes during iteration, as might happen if the collection permits
157      * concurrent modification during iteration.  The {@code size} method is
158      * called only as an optimization hint; the correct result is returned
159      * even if the iterator returns a different number of elements.
160      *
161      * <p>This method is equivalent to:
162      *
163      *  <pre> {@code
164      * List<E> list = new ArrayList<E>(size());
165      * for (E e : this)
166      *     list.add(e);
167      * return list.toArray(a);
168      * }</pre>
169      *
170      * @throws ArrayStoreException  {@inheritDoc}
171      * @throws NullPointerException {@inheritDoc}
172      */
toArray(T[] a)173     public <T> T[] toArray(T[] a) {
174         // Estimate size of array; be prepared to see more or fewer elements
175         int size = size();
176         T[] r = a.length >= size ? a :
177                   (T[])java.lang.reflect.Array
178                   .newInstance(a.getClass().getComponentType(), size);
179         Iterator<E> it = iterator();
180 
181         for (int i = 0; i < r.length; i++) {
182             if (! it.hasNext()) { // fewer elements than expected
183                 if (a == r) {
184                     r[i] = null; // null-terminate
185                 } else if (a.length < i) {
186                     return Arrays.copyOf(r, i);
187                 } else {
188                     System.arraycopy(r, 0, a, 0, i);
189                     if (a.length > i) {
190                         a[i] = null;
191                     }
192                 }
193                 return a;
194             }
195             r[i] = (T)it.next();
196         }
197         // more elements than expected
198         return it.hasNext() ? finishToArray(r, it) : r;
199     }
200 
201     /**
202      * The maximum size of array to allocate.
203      * Some VMs reserve some header words in an array.
204      * Attempts to allocate larger arrays may result in
205      * OutOfMemoryError: Requested array size exceeds VM limit
206      */
207     private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
208 
209     /**
210      * Reallocates the array being used within toArray when the iterator
211      * returned more elements than expected, and finishes filling it from
212      * the iterator.
213      *
214      * @param r the array, replete with previously stored elements
215      * @param it the in-progress iterator over this collection
216      * @return array containing the elements in the given array, plus any
217      *         further elements returned by the iterator, trimmed to size
218      */
finishToArray(T[] r, Iterator<?> it)219     private static <T> T[] finishToArray(T[] r, Iterator<?> it) {
220         int i = r.length;
221         while (it.hasNext()) {
222             int cap = r.length;
223             if (i == cap) {
224                 int newCap = cap + (cap >> 1) + 1;
225                 // overflow-conscious code
226                 if (newCap - MAX_ARRAY_SIZE > 0)
227                     newCap = hugeCapacity(cap + 1);
228                 r = Arrays.copyOf(r, newCap);
229             }
230             r[i++] = (T)it.next();
231         }
232         // trim if overallocated
233         return (i == r.length) ? r : Arrays.copyOf(r, i);
234     }
235 
hugeCapacity(int minCapacity)236     private static int hugeCapacity(int minCapacity) {
237         if (minCapacity < 0) // overflow
238             throw new OutOfMemoryError
239                 ("Required array size too large");
240         return (minCapacity > MAX_ARRAY_SIZE) ?
241             Integer.MAX_VALUE :
242             MAX_ARRAY_SIZE;
243     }
244 
245     // Modification Operations
246 
247     /**
248      * {@inheritDoc}
249      *
250      * <p>This implementation always throws an
251      * <tt>UnsupportedOperationException</tt>.
252      *
253      * @throws UnsupportedOperationException {@inheritDoc}
254      * @throws ClassCastException            {@inheritDoc}
255      * @throws NullPointerException          {@inheritDoc}
256      * @throws IllegalArgumentException      {@inheritDoc}
257      * @throws IllegalStateException         {@inheritDoc}
258      */
add(E e)259     public boolean add(E e) {
260         throw new UnsupportedOperationException();
261     }
262 
263     /**
264      * {@inheritDoc}
265      *
266      * <p>This implementation iterates over the collection looking for the
267      * specified element.  If it finds the element, it removes the element
268      * from the collection using the iterator's remove method.
269      *
270      * <p>Note that this implementation throws an
271      * <tt>UnsupportedOperationException</tt> if the iterator returned by this
272      * collection's iterator method does not implement the <tt>remove</tt>
273      * method and this collection contains the specified object.
274      *
275      * @throws UnsupportedOperationException {@inheritDoc}
276      * @throws ClassCastException            {@inheritDoc}
277      * @throws NullPointerException          {@inheritDoc}
278      */
remove(Object o)279     public boolean remove(Object o) {
280         Iterator<E> it = iterator();
281         if (o==null) {
282             while (it.hasNext()) {
283                 if (it.next()==null) {
284                     it.remove();
285                     return true;
286                 }
287             }
288         } else {
289             while (it.hasNext()) {
290                 if (o.equals(it.next())) {
291                     it.remove();
292                     return true;
293                 }
294             }
295         }
296         return false;
297     }
298 
299 
300     // Bulk Operations
301 
302     /**
303      * {@inheritDoc}
304      *
305      * <p>This implementation iterates over the specified collection,
306      * checking each element returned by the iterator in turn to see
307      * if it's contained in this collection.  If all elements are so
308      * contained <tt>true</tt> is returned, otherwise <tt>false</tt>.
309      *
310      * @throws ClassCastException            {@inheritDoc}
311      * @throws NullPointerException          {@inheritDoc}
312      * @see #contains(Object)
313      */
containsAll(Collection<?> c)314     public boolean containsAll(Collection<?> c) {
315         for (Object e : c)
316             if (!contains(e))
317                 return false;
318         return true;
319     }
320 
321     /**
322      * {@inheritDoc}
323      *
324      * <p>This implementation iterates over the specified collection, and adds
325      * each object returned by the iterator to this collection, in turn.
326      *
327      * <p>Note that this implementation will throw an
328      * <tt>UnsupportedOperationException</tt> unless <tt>add</tt> is
329      * overridden (assuming the specified collection is non-empty).
330      *
331      * @throws UnsupportedOperationException {@inheritDoc}
332      * @throws ClassCastException            {@inheritDoc}
333      * @throws NullPointerException          {@inheritDoc}
334      * @throws IllegalArgumentException      {@inheritDoc}
335      * @throws IllegalStateException         {@inheritDoc}
336      *
337      * @see #add(Object)
338      */
addAll(Collection<? extends E> c)339     public boolean addAll(Collection<? extends E> c) {
340         boolean modified = false;
341         for (E e : c)
342             if (add(e))
343                 modified = true;
344         return modified;
345     }
346 
347     /**
348      * {@inheritDoc}
349      *
350      * <p>This implementation iterates over this collection, checking each
351      * element returned by the iterator in turn to see if it's contained
352      * in the specified collection.  If it's so contained, it's removed from
353      * this collection with the iterator's <tt>remove</tt> method.
354      *
355      * <p>Note that this implementation will throw an
356      * <tt>UnsupportedOperationException</tt> if the iterator returned by the
357      * <tt>iterator</tt> method does not implement the <tt>remove</tt> method
358      * and this collection contains one or more elements in common with the
359      * specified collection.
360      *
361      * @throws UnsupportedOperationException {@inheritDoc}
362      * @throws ClassCastException            {@inheritDoc}
363      * @throws NullPointerException          {@inheritDoc}
364      *
365      * @see #remove(Object)
366      * @see #contains(Object)
367      */
removeAll(Collection<?> c)368     public boolean removeAll(Collection<?> c) {
369         boolean modified = false;
370         Iterator<?> it = iterator();
371         while (it.hasNext()) {
372             if (c.contains(it.next())) {
373                 it.remove();
374                 modified = true;
375             }
376         }
377         return modified;
378     }
379 
380     /**
381      * {@inheritDoc}
382      *
383      * <p>This implementation iterates over this collection, checking each
384      * element returned by the iterator in turn to see if it's contained
385      * in the specified collection.  If it's not so contained, it's removed
386      * from this collection with the iterator's <tt>remove</tt> method.
387      *
388      * <p>Note that this implementation will throw an
389      * <tt>UnsupportedOperationException</tt> if the iterator returned by the
390      * <tt>iterator</tt> method does not implement the <tt>remove</tt> method
391      * and this collection contains one or more elements not present in the
392      * specified collection.
393      *
394      * @throws UnsupportedOperationException {@inheritDoc}
395      * @throws ClassCastException            {@inheritDoc}
396      * @throws NullPointerException          {@inheritDoc}
397      *
398      * @see #remove(Object)
399      * @see #contains(Object)
400      */
retainAll(Collection<?> c)401     public boolean retainAll(Collection<?> c) {
402         boolean modified = false;
403         Iterator<E> it = iterator();
404         while (it.hasNext()) {
405             if (!c.contains(it.next())) {
406                 it.remove();
407                 modified = true;
408             }
409         }
410         return modified;
411     }
412 
413     /**
414      * {@inheritDoc}
415      *
416      * <p>This implementation iterates over this collection, removing each
417      * element using the <tt>Iterator.remove</tt> operation.  Most
418      * implementations will probably choose to override this method for
419      * efficiency.
420      *
421      * <p>Note that this implementation will throw an
422      * <tt>UnsupportedOperationException</tt> if the iterator returned by this
423      * collection's <tt>iterator</tt> method does not implement the
424      * <tt>remove</tt> method and this collection is non-empty.
425      *
426      * @throws UnsupportedOperationException {@inheritDoc}
427      */
clear()428     public void clear() {
429         Iterator<E> it = iterator();
430         while (it.hasNext()) {
431             it.next();
432             it.remove();
433         }
434     }
435 
436 
437     //  String conversion
438 
439     /**
440      * Returns a string representation of this collection.  The string
441      * representation consists of a list of the collection's elements in the
442      * order they are returned by its iterator, enclosed in square brackets
443      * (<tt>"[]"</tt>).  Adjacent elements are separated by the characters
444      * <tt>", "</tt> (comma and space).  Elements are converted to strings as
445      * by {@link String#valueOf(Object)}.
446      *
447      * @return a string representation of this collection
448      */
toString()449     public String toString() {
450         Iterator<E> it = iterator();
451         if (! it.hasNext())
452             return "[]";
453 
454         StringBuilder sb = new StringBuilder();
455         sb.append('[');
456         for (;;) {
457             E e = it.next();
458             sb.append(e == this ? "(this Collection)" : e);
459             if (! it.hasNext())
460                 return sb.append(']').toString();
461             sb.append(',').append(' ');
462         }
463     }
464 
465 }
466