1 |
/* AbstractCollection.java -- Abstract implementation of most of Collection |
/* AbstractCollection.java -- Abstract implementation of most of Collection |
2 |
Copyright (C) 1998, 2000 Free Software Foundation, Inc. |
Copyright (C) 1998, 2000, 2001 Free Software Foundation, Inc. |
3 |
|
|
4 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
5 |
|
|
42 |
* backing data structure allows for a more efficient implementation. The |
* backing data structure allows for a more efficient implementation. The |
43 |
* precise implementation used by AbstractCollection is documented, so that |
* precise implementation used by AbstractCollection is documented, so that |
44 |
* subclasses can tell which methods could be implemented more efficiently. |
* subclasses can tell which methods could be implemented more efficiently. |
45 |
|
* <p> |
46 |
|
* |
47 |
|
* The programmer should provide a no-argument constructor, and one that |
48 |
|
* accepts another Collection, as recommended by the Collection interface. |
49 |
|
* Unfortunately, there is no way to enforce this in Java. |
50 |
|
* |
51 |
|
* @author Original author unknown |
52 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
53 |
|
* @see Collection |
54 |
|
* @see AbstractSet |
55 |
|
* @see AbstractList |
56 |
|
* @since 1.2 |
57 |
|
* @status updated to 1.4 |
58 |
*/ |
*/ |
59 |
public abstract class AbstractCollection implements Collection |
public abstract class AbstractCollection implements Collection |
60 |
{ |
{ |
61 |
/** |
/** |
62 |
|
* The main constructor, for use by subclasses. |
63 |
|
*/ |
64 |
|
protected AbstractCollection() |
65 |
|
{ |
66 |
|
} |
67 |
|
|
68 |
|
/** |
69 |
* Return an Iterator over this collection. The iterator must provide the |
* Return an Iterator over this collection. The iterator must provide the |
70 |
* hasNext and next methods and should in addition provide remove if the |
* hasNext and next methods and should in addition provide remove if the |
71 |
* collection is modifiable. |
* collection is modifiable. |
72 |
|
* |
73 |
|
* @return an iterator |
74 |
*/ |
*/ |
75 |
public abstract Iterator iterator(); |
public abstract Iterator iterator(); |
76 |
|
|
77 |
/** |
/** |
78 |
* Return the number of elements in this collection. |
* Return the number of elements in this collection. If there are more than |
79 |
|
* Integer.MAX_VALUE elements, return Integer.MAX_VALUE. |
80 |
|
* |
81 |
|
* @return the size |
82 |
*/ |
*/ |
83 |
public abstract int size(); |
public abstract int size(); |
84 |
|
|
85 |
/** |
/** |
86 |
* Add an object to the collection. This implementation always throws an |
* Add an object to the collection (optional operation). This implementation |
87 |
* UnsupportedOperationException - it should be overridden if the collection |
* always throws an UnsupportedOperationException - it should be |
88 |
* is to be modifiable. |
* overridden if the collection is to be modifiable. If the collection |
89 |
|
* does not accept duplicates, simply return false. Collections may specify |
90 |
|
* limitations on what may be added. |
91 |
* |
* |
92 |
* @param o the object to add |
* @param o the object to add |
93 |
* @return true if the add operation caused the Collection to change |
* @return true if the add operation caused the Collection to change |
94 |
* @exception UnsupportedOperationException if the add operation is not |
* @throws UnsupportedOperationException if the add operation is not |
95 |
* supported on this collection |
* supported on this collection |
96 |
|
* @throws NullPointerException if the collection does not support null |
97 |
|
* @throws ClassCastException if the object is of the wrong type |
98 |
|
* @throws IllegalArgumentException if some aspect of the object prevents |
99 |
|
* it from being added |
100 |
*/ |
*/ |
101 |
public boolean add(Object o) |
public boolean add(Object o) |
102 |
{ |
{ |
103 |
throw new java.lang.UnsupportedOperationException(); |
throw new UnsupportedOperationException(); |
104 |
} |
} |
105 |
|
|
106 |
/** |
/** |
107 |
* Add all the elements of a given collection to this collection. This |
* Add all the elements of a given collection to this collection (optional |
108 |
* implementation obtains an Iterator over the given collection and iterates |
* operation). This implementation obtains an Iterator over the given |
109 |
* over it, adding each element with the add(Object) method (thus this method |
* collection and iterates over it, adding each element with the |
110 |
* will fail with an UnsupportedOperationException if the add method does). |
* add(Object) method (thus this method will fail with an |
111 |
|
* UnsupportedOperationException if the add method does). The behavior is |
112 |
|
* unspecified if the specified collection is modified during the iteration, |
113 |
|
* including the special case of trying addAll(this) on a non-empty |
114 |
|
* collection. |
115 |
* |
* |
116 |
* @param c the collection to add the elements of to this collection |
* @param c the collection to add the elements of to this collection |
117 |
* @return true if the add operation caused the Collection to change |
* @return true if the add operation caused the Collection to change |
118 |
* @exception UnsupportedOperationException if the add operation is not |
* @throws UnsupportedOperationException if the add operation is not |
119 |
* supported on this collection |
* supported on this collection |
120 |
|
* @throws NullPointerException if this collection does not support null, |
121 |
|
* or if the specified collection is null |
122 |
|
* @throws ClassCastException if an object in c is of the wrong type |
123 |
|
* @throws IllegalArgumentException if some aspect of an object in c prevents |
124 |
|
* it from being added |
125 |
|
* @see #add(Object) |
126 |
*/ |
*/ |
127 |
public boolean addAll(Collection c) |
public boolean addAll(Collection c) |
128 |
{ |
{ |
129 |
Iterator itr = c.iterator(); |
Iterator itr = c.iterator(); |
|
int size = c.size(); |
|
130 |
boolean modified = false; |
boolean modified = false; |
131 |
for (int pos = 0; pos < size; pos++) |
int pos = size(); |
132 |
{ |
while (--pos >= 0) |
133 |
modified |= add(itr.next()); |
modified |= add(itr.next()); |
|
} |
|
134 |
return modified; |
return modified; |
135 |
} |
} |
136 |
|
|
137 |
/** |
/** |
138 |
* Remove all elements from the collection. This implementation obtains an |
* Remove all elements from the collection (optional operation). This |
139 |
* iterator over the collection and calls next and remove on it repeatedly |
* implementation obtains an iterator over the collection and calls next |
140 |
* (thus this method will fail with an UnsupportedOperationException if the |
* and remove on it repeatedly (thus this method will fail with an |
141 |
* Iterator's remove method does) until there are no more elements to remove. |
* UnsupportedOperationException if the Iterator's remove method does) |
142 |
|
* until there are no more elements to remove. |
143 |
* Many implementations will have a faster way of doing this. |
* Many implementations will have a faster way of doing this. |
144 |
* |
* |
145 |
* @exception UnsupportedOperationException if the Iterator returned by |
* @throws UnsupportedOperationException if the Iterator returned by |
146 |
* iterator does not provide an implementation of remove |
* iterator does not provide an implementation of remove |
147 |
|
* @see Iterator#remove() |
148 |
*/ |
*/ |
149 |
public void clear() |
public void clear() |
150 |
{ |
{ |
151 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
152 |
int size = size(); |
int pos = size(); |
153 |
for (int pos = 0; pos < size; pos++) |
while (--pos >= 0) |
154 |
{ |
{ |
155 |
itr.next(); |
itr.next(); |
156 |
itr.remove(); |
itr.remove(); |
157 |
} |
} |
158 |
} |
} |
159 |
|
|
171 |
public boolean contains(Object o) |
public boolean contains(Object o) |
172 |
{ |
{ |
173 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
174 |
int size = size(); |
int pos = size(); |
175 |
for (int pos = 0; pos < size; pos++) |
while (--pos >= 0) |
176 |
{ |
if (equals(o, itr.next())) |
177 |
if (o == null ? itr.next() == null : o.equals(itr.next())) |
return true; |
|
return true; |
|
|
} |
|
178 |
return false; |
return false; |
179 |
} |
} |
180 |
|
|
186 |
* |
* |
187 |
* @param c the collection to test against |
* @param c the collection to test against |
188 |
* @return true if this collection contains all the elements in the given |
* @return true if this collection contains all the elements in the given |
189 |
* collection |
* collection |
190 |
|
* @throws NullPointerException if the given collection is null |
191 |
|
* @see #contains(Object) |
192 |
*/ |
*/ |
193 |
public boolean containsAll(Collection c) |
public boolean containsAll(Collection c) |
194 |
{ |
{ |
195 |
Iterator itr = c.iterator(); |
Iterator itr = c.iterator(); |
196 |
int size = c.size(); |
int pos = size(); |
197 |
for (int pos = 0; pos < size; pos++) |
while (--pos >= 0) |
198 |
{ |
if (!contains(itr.next())) |
199 |
if (!contains(itr.next())) |
return false; |
|
return false; |
|
|
} |
|
200 |
return true; |
return true; |
201 |
} |
} |
202 |
|
|
205 |
* size() == 0. |
* size() == 0. |
206 |
* |
* |
207 |
* @return true if this collection is empty. |
* @return true if this collection is empty. |
208 |
|
* @see #size() |
209 |
*/ |
*/ |
210 |
public boolean isEmpty() |
public boolean isEmpty() |
211 |
{ |
{ |
213 |
} |
} |
214 |
|
|
215 |
/** |
/** |
216 |
* Remove a single instance of an object from this collection. That is, |
* Remove a single instance of an object from this collection (optional |
217 |
* remove one element e such that (o == null ? e == null : o.equals(e)), if |
* operation). That is, remove one element e such that |
218 |
* such an element exists. This implementation obtains an iterator over the |
* <code>(o == null ? e == null : o.equals(e))</code>, if such an element |
219 |
* collection and iterates over it, testing each element for equality with |
* exists. This implementation obtains an iterator over the collection |
220 |
* the given object. If it is equal, it is removed by the iterator's remove |
* and iterates over it, testing each element for equality with the given |
221 |
* method (thus this method will fail with an UnsupportedOperationException |
* object. If it is equal, it is removed by the iterator's remove method |
222 |
* if the Iterator's remove method does). After the first element has been |
* (thus this method will fail with an UnsupportedOperationException if |
223 |
|
* the Iterator's remove method does). After the first element has been |
224 |
* removed, true is returned; if the end of the collection is reached, false |
* removed, true is returned; if the end of the collection is reached, false |
225 |
* is returned. |
* is returned. |
226 |
* |
* |
227 |
* @param o the object to remove from this collection |
* @param o the object to remove from this collection |
228 |
* @return true if the remove operation caused the Collection to change, or |
* @return true if the remove operation caused the Collection to change, or |
229 |
* equivalently if the collection did contain o. |
* equivalently if the collection did contain o. |
230 |
* @exception UnsupportedOperationException if this collection's Iterator |
* @throws UnsupportedOperationException if this collection's Iterator |
231 |
* does not support the remove method |
* does not support the remove method |
232 |
|
* @see Iterator#remove() |
233 |
*/ |
*/ |
234 |
public boolean remove(Object o) |
public boolean remove(Object o) |
235 |
{ |
{ |
236 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
237 |
int size = size(); |
int pos = size(); |
238 |
for (int pos = 0; pos < size; pos++) |
while (--pos >= 0) |
239 |
{ |
if (equals(o, itr.next())) |
240 |
if (o == null ? itr.next() == null : o.equals(itr.next())) |
{ |
241 |
{ |
itr.remove(); |
242 |
itr.remove(); |
return true; |
243 |
return true; |
} |
|
} |
|
|
} |
|
244 |
return false; |
return false; |
245 |
} |
} |
246 |
|
|
247 |
/** |
/** |
248 |
* Remove from this collection all its elements that are contained in a given |
* Remove from this collection all its elements that are contained in a given |
249 |
* collection. This implementation iterates over this collection, and for |
* collection (optional operation). This implementation iterates over this |
250 |
* each element tests if it is contained in the given collection. If so, it |
* collection, and for each element tests if it is contained in the given |
251 |
* is removed by the Iterator's remove method (thus this method will fail |
* collection. If so, it is removed by the Iterator's remove method (thus |
252 |
* with an UnsupportedOperationException if the Iterator's remove method |
* this method will fail with an UnsupportedOperationException if the |
253 |
* does). |
* Iterator's remove method does). |
254 |
* |
* |
255 |
* @param c the collection to remove the elements of |
* @param c the collection to remove the elements of |
256 |
* @return true if the remove operation caused the Collection to change |
* @return true if the remove operation caused the Collection to change |
257 |
* @exception UnsupportedOperationException if this collection's Iterator |
* @throws UnsupportedOperationException if this collection's Iterator |
258 |
* does not support the remove method |
* does not support the remove method |
259 |
|
* @see Iterator#remove() |
260 |
*/ |
*/ |
261 |
public boolean removeAll(Collection c) |
public boolean removeAll(Collection c) |
262 |
{ |
{ |
263 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
|
int size = size(); |
|
264 |
boolean modified = false; |
boolean modified = false; |
265 |
for (int pos = 0; pos < size; pos++) |
int pos = size(); |
266 |
{ |
while (--pos >= 0) |
267 |
if (c.contains(itr.next())) |
if (c.contains(itr.next())) |
268 |
{ |
{ |
269 |
itr.remove(); |
itr.remove(); |
270 |
modified = true; |
modified = true; |
271 |
} |
} |
|
} |
|
272 |
return modified; |
return modified; |
273 |
} |
} |
274 |
|
|
275 |
/** |
/** |
276 |
* Remove from this collection all its elements that are not contained in a |
* Remove from this collection all its elements that are not contained in a |
277 |
* given collection. This implementation iterates over this collection, and |
* given collection (optional operation). This implementation iterates over |
278 |
* for each element tests if it is contained in the given collection. If not, |
* this collection, and for each element tests if it is contained in the |
279 |
* it is removed by the Iterator's remove method (thus this method will fail |
* given collection. If not, it is removed by the Iterator's remove method |
280 |
* with an UnsupportedOperationException if the Iterator's remove method |
* (thus this method will fail with an UnsupportedOperationException if |
281 |
* does). |
* the Iterator's remove method does). |
282 |
* |
* |
283 |
* @param c the collection to retain the elements of |
* @param c the collection to retain the elements of |
284 |
* @return true if the remove operation caused the Collection to change |
* @return true if the remove operation caused the Collection to change |
285 |
* @exception UnsupportedOperationException if this collection's Iterator |
* @throws UnsupportedOperationException if this collection's Iterator |
286 |
* does not support the remove method |
* does not support the remove method |
287 |
|
* @see Iterator#remove() |
288 |
*/ |
*/ |
289 |
public boolean retainAll(Collection c) |
public boolean retainAll(Collection c) |
290 |
{ |
{ |
291 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
|
int size = size(); |
|
292 |
boolean modified = false; |
boolean modified = false; |
293 |
for (int pos = 0; pos < size; pos++) |
int pos = size(); |
294 |
{ |
while (--pos >= 0) |
295 |
if (!c.contains(itr.next())) |
if (!c.contains(itr.next())) |
296 |
{ |
{ |
297 |
itr.remove(); |
itr.remove(); |
298 |
modified = true; |
modified = true; |
299 |
} |
} |
|
} |
|
300 |
return modified; |
return modified; |
301 |
} |
} |
302 |
|
|
304 |
* Return an array containing the elements of this collection. This |
* Return an array containing the elements of this collection. This |
305 |
* implementation creates an Object array of size size() and then iterates |
* implementation creates an Object array of size size() and then iterates |
306 |
* over the collection, setting each element of the array from the value |
* over the collection, setting each element of the array from the value |
307 |
* returned by the iterator. |
* returned by the iterator. The returned array is safe, and is not backed |
308 |
|
* by the collection. |
309 |
* |
* |
310 |
* @return an array containing the elements of this collection |
* @return an array containing the elements of this collection |
311 |
*/ |
*/ |
312 |
public Object[] toArray() |
public Object[] toArray() |
313 |
{ |
{ |
314 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
315 |
Object[]a = new Object[size()]; |
int size = size(); |
316 |
for (int pos = 0; pos < a.length; pos++) |
Object[] a = new Object[size]; |
317 |
{ |
for (int pos = 0; pos < size; pos++) |
318 |
a[pos] = itr.next(); |
a[pos] = itr.next(); |
|
} |
|
319 |
return a; |
return a; |
320 |
} |
} |
321 |
|
|
331 |
* obtained over the collection and the elements are placed in the array as |
* obtained over the collection and the elements are placed in the array as |
332 |
* they are returned by the iterator. Finally the first spare element, if |
* they are returned by the iterator. Finally the first spare element, if |
333 |
* any, of the array is set to null, and the created array is returned. |
* any, of the array is set to null, and the created array is returned. |
334 |
|
* The returned array is safe; it is not backed by the collection. Note that |
335 |
|
* null may not mark the last element, if the collection allows null |
336 |
|
* elements. |
337 |
* |
* |
338 |
* @param a the array to copy into, or of the correct run-time type |
* @param a the array to copy into, or of the correct run-time type |
339 |
* @return the array that was produced |
* @return the array that was produced |
340 |
* @exception ClassCastException if the type of the array precludes holding |
* @throws NullPointerException if the given array is null |
341 |
* one of the elements of the Collection |
* @throws ArrayStoreException if the type of the array precludes holding |
342 |
|
* one of the elements of the Collection |
343 |
*/ |
*/ |
344 |
public Object[] toArray(Object[]a) |
public Object[] toArray(Object[] a) |
345 |
{ |
{ |
346 |
int size = size(); |
int size = size(); |
347 |
if (a.length < size) |
if (a.length < size) |
348 |
{ |
a = (Object[]) Array.newInstance(a.getClass().getComponentType(), |
349 |
a = (Object[])Array.newInstance(a.getClass().getComponentType(), |
size); |
350 |
size); |
else if (a.length > size) |
351 |
} |
a[size] = null; |
352 |
|
|
353 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
354 |
for (int pos = 0; pos < size; pos++) |
for (int pos = 0; pos < size; pos++) |
355 |
{ |
a[pos] = itr.next(); |
356 |
a[pos] = itr.next(); |
|
|
} |
|
|
if (a.length > size) |
|
|
{ |
|
|
a[size] = null; |
|
|
} |
|
357 |
return a; |
return a; |
358 |
} |
} |
359 |
|
|
369 |
public String toString() |
public String toString() |
370 |
{ |
{ |
371 |
Iterator itr = iterator(); |
Iterator itr = iterator(); |
|
int size = size(); |
|
372 |
StringBuffer r = new StringBuffer("["); |
StringBuffer r = new StringBuffer("["); |
373 |
for (int pos = 0; pos < size; pos++) |
for (int pos = size(); pos > 0; pos--) |
374 |
{ |
{ |
375 |
r.append(itr.next()); |
r.append(itr.next()); |
376 |
if (pos < size - 1) |
if (pos > 1) |
377 |
r.append(", "); |
r.append(", "); |
378 |
} |
} |
379 |
r.append("]"); |
r.append("]"); |
380 |
return r.toString(); |
return r.toString(); |
381 |
} |
} |
382 |
|
|
383 |
|
/** |
384 |
|
* Compare two objects according to Collection semantics. |
385 |
|
* |
386 |
|
* @param o1 the first object |
387 |
|
* @param o2 the second object |
388 |
|
* @return o1 == null ? o2 == null : o1.equals(o2) |
389 |
|
*/ |
390 |
|
// Package visible for use throughout java.util. |
391 |
|
// It may be inlined since it is final. |
392 |
|
static final boolean equals(Object o1, Object o2) |
393 |
|
{ |
394 |
|
return o1 == null ? o2 == null : o1.equals(o2); |
395 |
|
} |
396 |
|
|
397 |
|
/** |
398 |
|
* Hash an object according to Collection semantics. |
399 |
|
* |
400 |
|
* @param o the object to hash |
401 |
|
* @return o1 == null ? 0 : o1.hashCode() |
402 |
|
*/ |
403 |
|
// Package visible for use throughout java.util. |
404 |
|
// It may be inlined since it is final. |
405 |
|
static final int hashCode(Object o) |
406 |
|
{ |
407 |
|
return o == null ? 0 : o.hashCode(); |
408 |
|
} |
409 |
} |
} |