1 |
/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed |
/* ArrayList.java -- JDK1.2's answer to Vector; this is an array-backed |
2 |
implementation of the List interface |
implementation of the List interface |
3 |
Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
4 |
|
|
5 |
This file is part of GNU Classpath. |
This file is part of GNU Classpath. |
6 |
|
|
35 |
import java.io.ObjectOutputStream; |
import java.io.ObjectOutputStream; |
36 |
|
|
37 |
/** |
/** |
38 |
* An array-backed implementation of the List interface. ArrayList |
* An array-backed implementation of the List interface. This implements |
39 |
* performs well on simple tasks: random access into a list, appending |
* all optional list operations, and permits null elements, so that it is |
40 |
* to or removing from the end of a list, checking the size, &c. |
* better than Vector, which it replaces. Random access is roughly constant |
41 |
|
* time, and iteration is roughly linear time, so it is nice and fast, with |
42 |
|
* less overhead than a LinkedList. |
43 |
|
* <p> |
44 |
* |
* |
45 |
* @author Jon A. Zeppieri |
* Each list has a capacity, and as the array reaches that capacity it |
46 |
* @see java.util.AbstractList |
* is automatically transferred to a larger array. You also have access to |
47 |
* @see java.util.List |
* ensureCapacity and trimToSize to control the backing array's size, avoiding |
48 |
|
* reallocation or wasted memory. |
49 |
|
* <p> |
50 |
|
* |
51 |
|
* ArrayList is not synchronized, so if you need multi-threaded access, |
52 |
|
* consider using:<br> |
53 |
|
* <code>List l = Collections.synchronizedList(new ArrayList(...));</code> |
54 |
|
* <p> |
55 |
|
* |
56 |
|
* The iterators are <i>fail-fast</i>, meaning that any structural |
57 |
|
* modification, except for <code>remove()</code> called on the iterator |
58 |
|
* itself, cause the iterator to throw a |
59 |
|
* {@link ConcurrentModificationException} rather than exhibit |
60 |
|
* non-deterministic behavior. |
61 |
|
* |
62 |
|
* @author Jon A. Zeppieri |
63 |
|
* @author Eric Blake <ebb9@email.byu.edu> |
64 |
|
* @see Collection |
65 |
|
* @see List |
66 |
|
* @see LinkedList |
67 |
|
* @see Vector |
68 |
|
* @see Collections#synchronizedList(List) |
69 |
|
* @see AbstractList |
70 |
|
* @status updated to 1.4 |
71 |
*/ |
*/ |
72 |
public class ArrayList extends AbstractList |
public class ArrayList extends AbstractList |
73 |
implements List, Cloneable, Serializable |
implements List, RandomAccess, Cloneable, Serializable |
74 |
{ |
{ |
75 |
/** the default capacity for new ArrayLists */ |
/** |
76 |
|
* Compatible with JDK 1.2 |
77 |
|
*/ |
78 |
|
private static final long serialVersionUID = 8683452581122892189L; |
79 |
|
|
80 |
|
/** |
81 |
|
* The default capacity for new ArrayLists. |
82 |
|
*/ |
83 |
private static final int DEFAULT_CAPACITY = 16; |
private static final int DEFAULT_CAPACITY = 16; |
84 |
|
|
85 |
/** the number of elements in this list */ |
/** |
86 |
int size; |
* The number of elements in this list. |
87 |
|
* @serial the list size |
88 |
|
*/ |
89 |
|
private int size; |
90 |
|
|
91 |
/** where the data is stored */ |
/** |
92 |
transient Object[] data; |
* Where the data is stored. |
93 |
|
*/ |
94 |
|
private transient Object[] data; |
95 |
|
|
96 |
/** |
/** |
97 |
* Construct a new ArrayList with the supplied initial capacity. |
* Construct a new ArrayList with the supplied initial capacity. |
98 |
* |
* |
99 |
* @param capacity Initial capacity of this ArrayList |
* @param capacity initial capacity of this ArrayList |
100 |
|
* @throws IllegalArgumentException if capacity is negative |
101 |
*/ |
*/ |
102 |
public ArrayList(int capacity) |
public ArrayList(int capacity) |
103 |
{ |
{ |
104 |
|
// Must explicitly check, to get correct exception. |
105 |
|
if (capacity < 0) |
106 |
|
throw new IllegalArgumentException(); |
107 |
data = new Object[capacity]; |
data = new Object[capacity]; |
108 |
} |
} |
109 |
|
|
|
|
|
110 |
/** |
/** |
111 |
* Construct a new ArrayList with the default capcity |
* Construct a new ArrayList with the default capcity (16). |
112 |
*/ |
*/ |
113 |
public ArrayList() |
public ArrayList() |
114 |
{ |
{ |
115 |
this(DEFAULT_CAPACITY); |
this(DEFAULT_CAPACITY); |
116 |
} |
} |
117 |
|
|
118 |
/** |
/** |
119 |
* Construct a new ArrayList, and initialize it with the elements |
* Construct a new ArrayList, and initialize it with the elements |
120 |
* in the supplied Collection; Sun specs say that the initial |
* in the supplied Collection. The initial capacity is 110% of the |
121 |
* capacity is 110% of the Collection's size. |
* Collection's size. |
122 |
* |
* |
123 |
* @param c the collection whose elements will initialize this list |
* @param c the collection whose elements will initialize this list |
124 |
|
* @throws NullPointerException if c is null |
125 |
*/ |
*/ |
126 |
public ArrayList(Collection c) |
public ArrayList(Collection c) |
127 |
{ |
{ |
128 |
this((int) (c.size() * 1.1)); |
this((int) (c.size() * 1.1f)); |
129 |
addAll(c); |
addAll(c); |
130 |
} |
} |
131 |
|
|
132 |
/** |
/** |
133 |
|
* Trims the capacity of this List to be equal to its size; |
134 |
|
* a memory saver. |
135 |
|
*/ |
136 |
|
public void trimToSize() |
137 |
|
{ |
138 |
|
// Not a structural change from the perspective of iterators on this list, |
139 |
|
// so don't update modCount. |
140 |
|
if (size != data.length) |
141 |
|
{ |
142 |
|
Object[] newData = new Object[size]; |
143 |
|
System.arraycopy(data, 0, newData, 0, size); |
144 |
|
data = newData; |
145 |
|
} |
146 |
|
} |
147 |
|
|
148 |
|
/** |
149 |
* Guarantees that this list will have at least enough capacity to |
* Guarantees that this list will have at least enough capacity to |
150 |
* hold minCapacity elements. |
* hold minCapacity elements. This implementation will grow the list to |
151 |
|
* max(current * 2, minCapacity) if (minCapacity > current). The JCL says |
152 |
|
* explictly that "this method increases its capacity to minCap", while |
153 |
|
* the JDK 1.3 online docs specify that the list will grow to at least the |
154 |
|
* size specified. |
155 |
* |
* |
|
* @specnote This implementation will grow the list to |
|
|
* max(current * 2, minCapacity) if (minCapacity > current). The JCL says |
|
|
* explictly that "this method increases its capacity to minCap", while |
|
|
* the JDK 1.3 online docs specify that the list will grow to at least the |
|
|
* size specified. |
|
156 |
* @param minCapacity the minimum guaranteed capacity |
* @param minCapacity the minimum guaranteed capacity |
157 |
*/ |
*/ |
158 |
public void ensureCapacity(int minCapacity) |
public void ensureCapacity(int minCapacity) |
159 |
{ |
{ |
|
Object[] newData; |
|
160 |
int current = data.length; |
int current = data.length; |
161 |
|
|
162 |
if (minCapacity > current) |
if (minCapacity > current) |
163 |
{ |
{ |
164 |
newData = new Object[Math.max((current * 2), minCapacity)]; |
Object[] newData = new Object[Math.max(current * 2, minCapacity)]; |
165 |
System.arraycopy(data, 0, newData, 0, size); |
System.arraycopy(data, 0, newData, 0, size); |
166 |
data = newData; |
data = newData; |
167 |
} |
} |
168 |
} |
} |
169 |
|
|
170 |
/** |
/** |
171 |
* Appends the supplied element to the end of this list. |
* Returns the number of elements in this list. |
172 |
* |
* |
173 |
* @param e the element to be appended to this list |
* @return the list size |
174 |
*/ |
*/ |
175 |
public boolean add(Object e) |
public int size() |
176 |
{ |
{ |
177 |
modCount++; |
return size; |
|
if (size == data.length) |
|
|
ensureCapacity(size + 1); |
|
|
data[size++] = e; |
|
|
return true; |
|
178 |
} |
} |
179 |
|
|
180 |
/** |
/** |
181 |
* Retrieves the element at the user-supplied index. |
* Checks if the list is empty. |
182 |
* |
* |
183 |
* @param index the index of the element we are fetching |
* @return true if there are no elements |
|
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size()) |
|
184 |
*/ |
*/ |
185 |
public Object get(int index) |
public boolean isEmpty() |
186 |
{ |
{ |
187 |
if (index < 0 || index >= size) |
return size == 0; |
|
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + |
|
|
size); |
|
|
return data[index]; |
|
188 |
} |
} |
189 |
|
|
190 |
/** |
/** |
191 |
* Returns the number of elements in this list |
* Returns true iff element is in this ArrayList. |
192 |
|
* |
193 |
|
* @param e the element whose inclusion in the List is being tested |
194 |
|
* @return true if the list contains e |
195 |
*/ |
*/ |
196 |
public int size() |
public boolean contains(Object e) |
197 |
{ |
{ |
198 |
return size; |
return indexOf(e) != -1; |
199 |
} |
} |
200 |
|
|
201 |
/** |
/** |
202 |
* Removes the element at the user-supplied index |
* Returns the lowest index at which element appears in this List, or |
203 |
|
* -1 if it does not appear. |
204 |
* |
* |
205 |
* @param iIndex the index of the element to be removed |
* @param e the element whose inclusion in the List is being tested |
206 |
* @return the removed Object |
* @return the index where e was found |
|
* @throws IndexOutOfBoundsException (iIndex < 0) || (iIndex >= size()) |
|
207 |
*/ |
*/ |
208 |
public Object remove(int index) |
public int indexOf(Object e) |
209 |
{ |
{ |
210 |
modCount++; |
for (int i = 0; i < size; i++) |
211 |
if (index < 0 || index > size) |
if (equals(e, data[i])) |
212 |
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + |
return i; |
213 |
size); |
return -1; |
|
Object r = data[index]; |
|
|
if (index != --size) |
|
|
System.arraycopy(data, (index + 1), data, index, (size - index)); |
|
|
data[size] = null; |
|
|
return r; |
|
214 |
} |
} |
215 |
|
|
216 |
/** |
/** |
217 |
* Removes all elements in the half-open interval [iFromIndex, iToIndex). |
* Returns the highest index at which element appears in this List, or |
218 |
|
* -1 if it does not appear. |
219 |
* |
* |
220 |
* @param fromIndex the first index which will be removed |
* @param e the element whose inclusion in the List is being tested |
221 |
* @param toIndex one greater than the last index which will be |
* @return the index where e was found |
|
* removed |
|
222 |
*/ |
*/ |
223 |
protected void removeRange(int fromIndex, int toIndex) |
public int lastIndexOf(Object e) |
224 |
{ |
{ |
225 |
modCount++; |
for (int i = size - 1; i >= 0; i--) |
226 |
if (fromIndex != toIndex) |
if (equals(e, data[i])) |
227 |
{ |
return i; |
228 |
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex); |
return -1; |
|
size -= (toIndex - fromIndex); |
|
|
} |
|
229 |
} |
} |
230 |
|
|
231 |
/** |
/** |
232 |
* Adds the supplied element at the specified index, shifting all |
* Creates a shallow copy of this ArrayList (elements are not cloned). |
|
* elements currently at that index or higher one to the right. |
|
233 |
* |
* |
234 |
* @param index the index at which the element is being added |
* @return the cloned object |
|
* @param e the item being added |
|
235 |
*/ |
*/ |
236 |
public void add(int index, Object e) |
public Object clone() |
237 |
{ |
{ |
238 |
modCount++; |
ArrayList clone = null; |
239 |
if (index < 0 || index > size) |
try |
240 |
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + |
{ |
241 |
size); |
clone = (ArrayList) super.clone(); |
242 |
if (size == data.length) |
clone.data = (Object[]) data.clone(); |
243 |
ensureCapacity(size + 1); |
} |
244 |
if (index != size) |
catch (CloneNotSupportedException e) |
245 |
System.arraycopy(data, index, data, index + 1, size - index); |
{ |
246 |
data[index] = e; |
// Impossible to get here. |
247 |
size++; |
} |
248 |
|
return clone; |
249 |
} |
} |
250 |
|
|
251 |
/** |
/** |
252 |
* Add each element in the supplied Collection to this List. |
* Returns an Object array containing all of the elements in this ArrayList. |
253 |
|
* The array is independent of this list. |
254 |
* |
* |
255 |
* @param c a Collection containing elements to be |
* @return an array representation of this list |
|
* added to this List |
|
256 |
*/ |
*/ |
257 |
public boolean addAll(Collection c) |
public Object[] toArray() |
258 |
{ |
{ |
259 |
return addAll(size, c); |
Object[] array = new Object[size]; |
260 |
|
System.arraycopy(data, 0, array, 0, size); |
261 |
|
return array; |
262 |
} |
} |
263 |
|
|
264 |
/** |
/** |
265 |
* Add all elements in the supplied collection, inserting them beginning |
* Returns an Array whose component type is the runtime component type of |
266 |
* at the specified index. |
* the passed-in Array. The returned Array is populated with all of the |
267 |
|
* elements in this ArrayList. If the passed-in Array is not large enough |
268 |
|
* to store all of the elements in this List, a new Array will be created |
269 |
|
* and returned; if the passed-in Array is <i>larger</i> than the size |
270 |
|
* of this List, then size() index will be set to null. |
271 |
|
* |
272 |
|
* @param a the passed-in Array |
273 |
|
* @return an array representation of this list |
274 |
|
* @throws ArrayStoreException if the runtime type of a does not allow |
275 |
|
* an element in this list |
276 |
|
* @throws NullPointerException if a is null |
277 |
|
*/ |
278 |
|
public Object[] toArray(Object[] a) |
279 |
|
{ |
280 |
|
if (a.length < size) |
281 |
|
a = (Object[]) Array.newInstance(a.getClass().getComponentType(), |
282 |
|
size); |
283 |
|
else if (a.length > size) |
284 |
|
a[size] = null; |
285 |
|
System.arraycopy(data, 0, a, 0, size); |
286 |
|
return a; |
287 |
|
} |
288 |
|
|
289 |
|
/** |
290 |
|
* Retrieves the element at the user-supplied index. |
291 |
* |
* |
292 |
* @param index the index at which the elements will be inserted |
* @param index the index of the element we are fetching |
293 |
* @param c the Collection containing the elements to be |
* @throws IndexOutOfBoundsException if index < 0 || index >= size() |
|
* inserted |
|
294 |
*/ |
*/ |
295 |
public boolean addAll(int index, Collection c) |
public Object get(int index) |
296 |
{ |
{ |
297 |
if (index < 0 || index > size) |
rangeExclusive(index); |
298 |
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + |
return data[index]; |
|
size); |
|
|
modCount++; |
|
|
Iterator itr = c.iterator(); |
|
|
int csize = c.size(); |
|
|
|
|
|
if (csize + size > data.length) |
|
|
ensureCapacity(size + csize); |
|
|
int end = index + csize; |
|
|
if (size > 0 && index != size) |
|
|
System.arraycopy(data, index, data, end, csize); |
|
|
size += csize; |
|
|
for (; index < end; index++) |
|
|
{ |
|
|
data[index] = itr.next(); |
|
|
} |
|
|
return (csize > 0); |
|
299 |
} |
} |
300 |
|
|
301 |
/** |
/** |
302 |
* Creates a shallow copy of this ArrayList |
* Sets the element at the specified index. |
303 |
|
* |
304 |
|
* @param index the index at which the element is being set |
305 |
|
* @param e the element to be set |
306 |
|
* @return the element previously at the specified index |
307 |
|
* @throws IndexOutOfBoundsException if index < 0 || index >= 0 |
308 |
*/ |
*/ |
309 |
public Object clone() |
public Object set(int index, Object e) |
310 |
{ |
{ |
311 |
ArrayList clone = null; |
rangeExclusive(index); |
312 |
try |
Object result = data[index]; |
313 |
{ |
data[index] = e; |
314 |
clone = (ArrayList) super.clone(); |
return result; |
|
clone.data = new Object[data.length]; |
|
|
System.arraycopy(data, 0, clone.data, 0, size); |
|
|
} |
|
|
catch (CloneNotSupportedException e) {} |
|
|
return clone; |
|
315 |
} |
} |
316 |
|
|
317 |
/** |
/** |
318 |
* Returns true iff oElement is in this ArrayList. |
* Appends the supplied element to the end of this list. |
319 |
* |
* |
320 |
* @param e the element whose inclusion in the List is being |
* @param e the element to be appended to this list |
321 |
* tested |
* @return true, the add will always succeed |
322 |
*/ |
*/ |
323 |
public boolean contains(Object e) |
public boolean add(Object e) |
324 |
{ |
{ |
325 |
return (indexOf(e) != -1); |
modCount++; |
326 |
|
if (size == data.length) |
327 |
|
ensureCapacity(size + 1); |
328 |
|
data[size++] = e; |
329 |
|
return true; |
330 |
} |
} |
331 |
|
|
332 |
/** |
/** |
333 |
* Returns the lowest index at which oElement appears in this List, or |
* Adds the supplied element at the specified index, shifting all |
334 |
* -1 if it does not appear. |
* elements currently at that index or higher one to the right. |
335 |
* |
* |
336 |
* @param e the element whose inclusion in the List is being |
* @param index the index at which the element is being added |
337 |
* tested |
* @param e the item being added |
338 |
|
* @throws IndexOutOfBoundsException if index < 0 || index > size() |
339 |
*/ |
*/ |
340 |
public int indexOf(Object e) |
public void add(int index, Object e) |
341 |
{ |
{ |
342 |
for (int i = 0; i < size; i++) |
rangeInclusive(index); |
343 |
{ |
modCount++; |
344 |
if (e == null ? data[i] == null : e.equals(data[i])) |
if (size == data.length) |
345 |
return i; |
ensureCapacity(size + 1); |
346 |
} |
if (index != size) |
347 |
return -1; |
System.arraycopy(data, index, data, index + 1, size - index); |
348 |
|
data[index] = e; |
349 |
|
size++; |
350 |
} |
} |
351 |
|
|
352 |
/** |
/** |
353 |
* Returns the highest index at which oElement appears in this List, or |
* Removes the element at the user-supplied index. |
|
* -1 if it does not appear. |
|
354 |
* |
* |
355 |
* @param e the element whose inclusion in the List is being |
* @param index the index of the element to be removed |
356 |
* tested |
* @return the removed Object |
357 |
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size() |
358 |
*/ |
*/ |
359 |
public int lastIndexOf(Object e) |
public Object remove(int index) |
360 |
{ |
{ |
361 |
int i; |
rangeExclusive(index); |
362 |
|
Object r = data[index]; |
363 |
for (i = size - 1; i >= 0; i--) |
modCount++; |
364 |
{ |
if (index != --size) |
365 |
if (e == null ? data[i] == null : e.equals(data[i])) |
System.arraycopy(data, index + 1, data, index, size - index); |
366 |
return i; |
// Aid for garbage collection by releasing this pointer. |
367 |
} |
data[size] = null; |
368 |
return -1; |
return r; |
369 |
} |
} |
370 |
|
|
371 |
/** |
/** |
373 |
*/ |
*/ |
374 |
public void clear() |
public void clear() |
375 |
{ |
{ |
376 |
modCount++; |
if (size > 0) |
|
for (int i = 0; i < size; i++) |
|
377 |
{ |
{ |
378 |
data[i] = null; |
modCount++; |
379 |
} |
// Allow for garbage collection. |
380 |
size = 0; |
Arrays.fill(data, 0, size, null); |
381 |
|
size = 0; |
382 |
|
} |
383 |
} |
} |
384 |
|
|
385 |
/** |
/** |
386 |
* Sets the element at the specified index. |
* Add each element in the supplied Collection to this List. It is undefined |
387 |
|
* what happens if you modify the list while this is taking place; for |
388 |
|
* example, if the collection contains this list. |
389 |
|
* |
390 |
|
* @param c a Collection containing elements to be added to this List |
391 |
|
* @return true if the list was modified, in other words c is not empty |
392 |
|
* @throws NullPointerException if c is null |
393 |
|
*/ |
394 |
|
public boolean addAll(Collection c) |
395 |
|
{ |
396 |
|
return addAll(size, c); |
397 |
|
} |
398 |
|
|
399 |
|
/** |
400 |
|
* Add all elements in the supplied collection, inserting them beginning |
401 |
|
* at the specified index. |
402 |
* |
* |
403 |
* @param index the index at which the element is being set |
* @param index the index at which the elements will be inserted |
404 |
* @param e the element to be set |
* @param c the Collection containing the elements to be inserted |
405 |
* @return the element previously at the specified index, or null if |
* @throws IndexOutOfBoundsException if index < 0 || index > 0 |
406 |
* none was there |
* @throws NullPointerException if c is null |
407 |
*/ |
*/ |
408 |
public Object set(int index, Object e) |
public boolean addAll(int index, Collection c) |
409 |
{ |
{ |
410 |
Object result; |
rangeInclusive(index); |
411 |
if (index < 0 || index >= size) |
Iterator itr = c.iterator(); |
412 |
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + |
int csize = c.size(); |
413 |
size); |
|
414 |
result = data[index]; |
modCount++; |
415 |
// SEH: no structural change, so don't update modCount |
if (csize + size > data.length) |
416 |
data[index] = e; |
ensureCapacity(size + csize); |
417 |
return result; |
int end = index + csize; |
418 |
|
if (index != size) |
419 |
|
System.arraycopy(data, index, data, end, csize); |
420 |
|
size += csize; |
421 |
|
for ( ; index < end; index++) |
422 |
|
data[index] = itr.next(); |
423 |
|
return csize > 0; |
424 |
} |
} |
425 |
|
|
426 |
/** |
/** |
427 |
* Returns an Object Array containing all of the elements in this ArrayList |
* Removes all elements in the half-open interval [fromIndex, toIndex). |
428 |
|
* You asked for it if you call this with invalid arguments. |
429 |
|
* |
430 |
|
* @param fromIndex the first index which will be removed |
431 |
|
* @param toIndex one greater than the last index which will be removed |
432 |
*/ |
*/ |
433 |
public Object[] toArray() |
protected void removeRange(int fromIndex, int toIndex) |
434 |
{ |
{ |
435 |
Object[] array = new Object[size]; |
if (fromIndex != toIndex) |
436 |
System.arraycopy(data, 0, array, 0, size); |
{ |
437 |
return array; |
modCount++; |
438 |
|
System.arraycopy(data, toIndex, data, fromIndex, size - toIndex); |
439 |
|
size -= toIndex - fromIndex; |
440 |
|
} |
441 |
} |
} |
442 |
|
|
443 |
/** |
/** |
444 |
* Returns an Array whose component type is the runtime component type of |
* Checks that the index is in the range of possible elements (inclusive). |
|
* the passed-in Array. The returned Array is populated with all of the |
|
|
* elements in this ArrayList. If the passed-in Array is not large enough |
|
|
* to store all of the elements in this List, a new Array will be created |
|
|
* and returned; if the passed-in Array is <i>larger</i> than the size |
|
|
* of this List, then size() index will be set to null. |
|
445 |
* |
* |
446 |
* @param array the passed-in Array |
* @param index the index to check |
447 |
|
* @throws IndexOutOfBoundsException if index < 0 || index > size |
448 |
*/ |
*/ |
449 |
public Object[] toArray(Object[] array) |
private void rangeInclusive(int index) |
450 |
{ |
{ |
451 |
if (array.length < size) |
// Implementation note: we do not check for negative ranges here, since |
452 |
array = (Object[]) Array.newInstance(array.getClass().getComponentType(), |
// that will cause an ArrayIndexOutOfBoundsException, a subclass of |
453 |
size); |
// the required exception, with no effort on our part. |
454 |
else if (array.length > size) |
if (index > size) |
455 |
array[size] = null; |
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" |
456 |
System.arraycopy(data, 0, array, 0, size); |
+ size); |
|
return array; |
|
457 |
} |
} |
458 |
|
|
459 |
/** |
/** |
460 |
* Trims the capacity of this List to be equal to its size; |
* Checks that the index is in the range of existing elements (exclusive). |
461 |
* a memory saver. |
* |
462 |
|
* @param index the index to check |
463 |
|
* @throws IndexOutOfBoundsException if index < 0 || index >= size |
464 |
*/ |
*/ |
465 |
public void trimToSize() |
private void rangeExclusive(int index) |
466 |
{ |
{ |
467 |
// not a structural change from the perspective of iterators on this list, |
// Implementation note: we do not check for negative ranges here, since |
468 |
// so don't update modCount |
// that will cause an ArrayIndexOutOfBoundsException, a subclass of |
469 |
Object[] newData = new Object[size]; |
// the required exception, with no effort on our part. |
470 |
System.arraycopy(data, 0, newData, 0, size); |
if (index >= size) |
471 |
data = newData; |
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" |
472 |
|
+ size); |
473 |
} |
} |
474 |
|
|
475 |
|
/** |
476 |
|
* Serializes this object to the given stream. |
477 |
|
* |
478 |
|
* @param out the stream to write to |
479 |
|
* @throws IOException if the underlying stream fails |
480 |
|
* @serialData the size field (int), the length of the backing array |
481 |
|
* (int), followed by its elements (Objects) in proper order. |
482 |
|
*/ |
483 |
private void writeObject(ObjectOutputStream out) throws IOException |
private void writeObject(ObjectOutputStream out) throws IOException |
484 |
{ |
{ |
485 |
int i; |
int len = data.length; |
486 |
|
|
487 |
// The 'size' field. |
// The 'size' field. |
488 |
out.defaultWriteObject(); |
out.defaultWriteObject(); |
489 |
|
|
490 |
// FIXME: Do we really want to serialize unused list entries?? |
// We serialize unused list entries to preserve capacity. |
491 |
out.writeInt(data.length); |
out.writeInt(len); |
492 |
for (i = 0; i < data.length; i++) |
for (int i = 0; i < len; i++) |
493 |
out.writeObject(data[i]); |
out.writeObject(data[i]); |
494 |
} |
} |
495 |
|
|
496 |
|
/** |
497 |
|
* Deserializes this object from the given stream. |
498 |
|
* |
499 |
|
* @param in the stream to read from |
500 |
|
* @throws ClassNotFoundException if the underlying stream fails |
501 |
|
* @throws IOException if the underlying stream fails |
502 |
|
* @serialData the size field (int), the length of the backing array |
503 |
|
* (int), followed by its elements (Objects) in proper order. |
504 |
|
*/ |
505 |
private void readObject(ObjectInputStream in) |
private void readObject(ObjectInputStream in) |
506 |
throws IOException, ClassNotFoundException |
throws IOException, ClassNotFoundException |
507 |
{ |
{ |
|
int i; |
|
|
int capacity; |
|
|
|
|
508 |
// the `size' field. |
// the `size' field. |
509 |
in.defaultReadObject(); |
in.defaultReadObject(); |
510 |
|
|
511 |
capacity = in.readInt(); |
int capacity = in.readInt(); |
512 |
data = new Object[capacity]; |
data = new Object[capacity]; |
513 |
|
|
514 |
for (i = 0; i < capacity; i++) |
for (int i = 0; i < capacity; i++) |
515 |
data[i] = in.readObject(); |
data[i] = in.readObject(); |
516 |
} |
} |
517 |
} |
} |