~ubuntu-branches/ubuntu/oneiric/libcommons-collections-java/oneiric

« back to all changes in this revision

Viewing changes to src/java/org/apache/commons/collections/FastArrayList.java

  • Committer: Bazaar Package Importer
  • Author(s): Takashi Okamoto
  • Date: 2004-08-07 00:02:50 UTC
  • Revision ID: james.westby@ubuntu.com-20040807000250-hcnqvrdpxg95nmzr
Tags: upstream-2.1.1
ImportĀ upstreamĀ versionĀ 2.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 1999-2004 The Apache Software Foundation
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
package org.apache.commons.collections;
 
17
 
 
18
 
 
19
import java.util.ArrayList;
 
20
import java.util.Collection;
 
21
import java.util.ConcurrentModificationException;
 
22
import java.util.Iterator;
 
23
import java.util.List;
 
24
import java.util.ListIterator;
 
25
 
 
26
 
 
27
/**
 
28
 * <p>A customized implementation of <code>java.util.ArrayList</code> designed
 
29
 * to operate in a multithreaded environment where the large majority of
 
30
 * method calls are read-only, instead of structural changes.  When operating
 
31
 * in "fast" mode, read calls are non-synchronized and write calls perform the
 
32
 * following steps:</p>
 
33
 * <ul>
 
34
 * <li>Clone the existing collection
 
35
 * <li>Perform the modification on the clone
 
36
 * <li>Replace the existing collection with the (modified) clone
 
37
 * </ul>
 
38
 * <p>When first created, objects of this class default to "slow" mode, where
 
39
 * all accesses of any type are synchronized but no cloning takes place.  This
 
40
 * is appropriate for initially populating the collection, followed by a switch
 
41
 * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
 
42
 * is complete.</p>
 
43
 *
 
44
 * <p><strong>NOTE</strong>: If you are creating and accessing an
 
45
 * <code>ArrayList</code> only within a single thread, you should use
 
46
 * <code>java.util.ArrayList</code> directly (with no synchronization), for
 
47
 * maximum performance.</p>
 
48
 *
 
49
 * <P><strong>NOTE</strong>: <I>This class is not cross-platform.
 
50
 * Using it may cause unexpected failures on some architectures.</I>
 
51
 * It suffers from the same problems as the double-checked locking idiom.  
 
52
 * In particular, the instruction that clones the internal collection and the 
 
53
 * instruction that sets the internal reference to the clone can be executed 
 
54
 * or perceived out-of-order.  This means that any read operation might fail 
 
55
 * unexpectedly, as it may be reading the state of the internal collection
 
56
 * before the internal collection is fully formed.
 
57
 * For more information on the double-checked locking idiom, see the
 
58
 * <A Href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
 
59
 * Double-Checked Locking Idiom Is Broken Declartion</A>.</P>
 
60
 *
 
61
 * @since 1.0
 
62
 * @author Craig R. McClanahan
 
63
 * @version $Revision: 1.9.2.1 $ $Date: 2004/05/22 12:14:02 $
 
64
 */
 
65
 
 
66
public class FastArrayList extends ArrayList {
 
67
 
 
68
 
 
69
    // ----------------------------------------------------------- Constructors
 
70
 
 
71
 
 
72
    /**
 
73
     * Construct a an empty list.
 
74
     */
 
75
    public FastArrayList() {
 
76
 
 
77
        super();
 
78
        this.list = new ArrayList();
 
79
 
 
80
    }
 
81
 
 
82
 
 
83
    /**
 
84
     * Construct an empty list with the specified capacity.
 
85
     *
 
86
     * @param capacity The initial capacity of the empty list
 
87
     */
 
88
    public FastArrayList(int capacity) {
 
89
 
 
90
        super();
 
91
        this.list = new ArrayList(capacity);
 
92
 
 
93
    }
 
94
 
 
95
 
 
96
    /**
 
97
     * Construct a list containing the elements of the specified collection,
 
98
     * in the order they are returned by the collection's iterator.
 
99
     *
 
100
     * @param collection The collection whose elements initialize the contents
 
101
     *  of this list
 
102
     */
 
103
    public FastArrayList(Collection collection) {
 
104
 
 
105
        super();
 
106
        this.list = new ArrayList(collection);
 
107
 
 
108
    }
 
109
 
 
110
 
 
111
    // ----------------------------------------------------- Instance Variables
 
112
 
 
113
 
 
114
    /**
 
115
     * The underlying list we are managing.
 
116
     */
 
117
    protected ArrayList list = null;
 
118
 
 
119
 
 
120
    // ------------------------------------------------------------- Properties
 
121
 
 
122
 
 
123
    /**
 
124
     * Are we operating in "fast" mode?
 
125
     */
 
126
    protected boolean fast = false;
 
127
 
 
128
 
 
129
    /**
 
130
     *  Returns true if this list is operating in fast mode.
 
131
     *
 
132
     *  @return true if this list is operating in fast mode
 
133
     */
 
134
    public boolean getFast() {
 
135
        return (this.fast);
 
136
    }
 
137
 
 
138
    /**
 
139
     *  Sets whether this list will operate in fast mode.
 
140
     *
 
141
     *  @param fast true if the list should operate in fast mode
 
142
     */
 
143
    public void setFast(boolean fast) {
 
144
        this.fast = fast;
 
145
    }
 
146
 
 
147
 
 
148
    // --------------------------------------------------------- Public Methods
 
149
 
 
150
 
 
151
    /**
 
152
     * Appends the specified element to the end of this list.
 
153
     *
 
154
     * @param element The element to be appended
 
155
     */
 
156
    public boolean add(Object element) {
 
157
 
 
158
        if (fast) {
 
159
            synchronized (this) {
 
160
                ArrayList temp = (ArrayList) list.clone();
 
161
                boolean result = temp.add(element);
 
162
                list = temp;
 
163
                return (result);
 
164
            }
 
165
        } else {
 
166
            synchronized (list) {
 
167
                return (list.add(element));
 
168
            }
 
169
        }
 
170
 
 
171
    }
 
172
 
 
173
 
 
174
    /**
 
175
     * Insert the specified element at the specified position in this list,
 
176
     * and shift all remaining elements up one position.
 
177
     *
 
178
     * @param index Index at which to insert this element
 
179
     * @param element The element to be inserted
 
180
     *
 
181
     * @exception IndexOutOfBoundsException if the index is out of range
 
182
     */
 
183
    public void add(int index, Object element) {
 
184
 
 
185
        if (fast) {
 
186
            synchronized (this) {
 
187
                ArrayList temp = (ArrayList) list.clone();
 
188
                temp.add(index, element);
 
189
                list = temp;
 
190
            }
 
191
        } else {
 
192
            synchronized (list) {
 
193
                list.add(index, element);
 
194
            }
 
195
        }
 
196
 
 
197
    }
 
198
 
 
199
 
 
200
    /**
 
201
     * Append all of the elements in the specified Collection to the end
 
202
     * of this list, in the order that they are returned by the specified
 
203
     * Collection's Iterator.
 
204
     *
 
205
     * @param collection The collection to be appended
 
206
     */
 
207
    public boolean addAll(Collection collection) {
 
208
 
 
209
        if (fast) {
 
210
            synchronized (this) {
 
211
                ArrayList temp = (ArrayList) list.clone();
 
212
                boolean result = temp.addAll(collection);
 
213
                list = temp;
 
214
                return (result);
 
215
            }
 
216
        } else {
 
217
            synchronized (list) {
 
218
                return (list.addAll(collection));
 
219
            }
 
220
        }
 
221
 
 
222
    }
 
223
 
 
224
 
 
225
    /**
 
226
     * Insert all of the elements in the specified Collection at the specified
 
227
     * position in this list, and shift any previous elements upwards as
 
228
     * needed.
 
229
     *
 
230
     * @param index Index at which insertion takes place
 
231
     * @param collection The collection to be added
 
232
     *
 
233
     * @exception IndexOutOfBoundsException if the index is out of range
 
234
     */
 
235
    public boolean addAll(int index, Collection collection) {
 
236
 
 
237
        if (fast) {
 
238
            synchronized (this) {
 
239
                ArrayList temp = (ArrayList) list.clone();
 
240
                boolean result = temp.addAll(index, collection);
 
241
                list = temp;
 
242
                return (result);
 
243
            }
 
244
        } else {
 
245
            synchronized (list) {
 
246
                return (list.addAll(index, collection));
 
247
            }
 
248
        }
 
249
 
 
250
    }
 
251
 
 
252
 
 
253
    /**
 
254
     * Remove all of the elements from this list.  The list will be empty
 
255
     * after this call returns.
 
256
     *
 
257
     * @exception UnsupportedOperationException if <code>clear()</code>
 
258
     *  is not supported by this list
 
259
     */
 
260
    public void clear() {
 
261
 
 
262
        if (fast) {
 
263
            synchronized (this) {
 
264
                ArrayList temp = (ArrayList) list.clone();
 
265
                temp.clear();
 
266
                list = temp;
 
267
            }
 
268
        } else {
 
269
            synchronized (list) {
 
270
                list.clear();
 
271
            }
 
272
        }
 
273
 
 
274
    }
 
275
 
 
276
 
 
277
    /**
 
278
     * Return a shallow copy of this <code>FastArrayList</code> instance.
 
279
     * The elements themselves are not copied.
 
280
     */
 
281
    public Object clone() {
 
282
 
 
283
        FastArrayList results = null;
 
284
        if (fast) {
 
285
            results = new FastArrayList(list);
 
286
        } else {
 
287
            synchronized (list) {
 
288
                results = new FastArrayList(list);
 
289
            }
 
290
        }
 
291
        results.setFast(getFast());
 
292
        return (results);
 
293
 
 
294
    }
 
295
 
 
296
 
 
297
    /**
 
298
     * Return <code>true</code> if this list contains the specified element.
 
299
     *
 
300
     * @param element The element to test for
 
301
     */
 
302
    public boolean contains(Object element) {
 
303
 
 
304
        if (fast) {
 
305
            return (list.contains(element));
 
306
        } else {
 
307
            synchronized (list) {
 
308
                return (list.contains(element));
 
309
            }
 
310
        }
 
311
 
 
312
    }
 
313
 
 
314
 
 
315
    /**
 
316
     * Return <code>true</code> if this list contains all of the elements
 
317
     * in the specified Collection.
 
318
     *
 
319
     * @param collection Collection whose elements are to be checked
 
320
     */
 
321
    public boolean containsAll(Collection collection) {
 
322
 
 
323
        if (fast) {
 
324
            return (list.containsAll(collection));
 
325
        } else {
 
326
            synchronized (list) {
 
327
                return (list.containsAll(collection));
 
328
            }
 
329
        }
 
330
 
 
331
    }
 
332
 
 
333
 
 
334
    /**
 
335
     * Increase the capacity of this <code>ArrayList</code> instance, if
 
336
     * necessary, to ensure that it can hold at least the number of elements
 
337
     * specified by the minimum capacity argument.
 
338
     *
 
339
     * @param capacity The new minimum capacity
 
340
     */
 
341
    public void ensureCapacity(int capacity) {
 
342
 
 
343
        if (fast) {
 
344
            synchronized (this) {
 
345
                ArrayList temp = (ArrayList) list.clone();
 
346
                temp.ensureCapacity(capacity);
 
347
                list = temp;
 
348
            }
 
349
        } else {
 
350
            synchronized (list) {
 
351
                list.ensureCapacity(capacity);
 
352
            }
 
353
        }
 
354
 
 
355
    }
 
356
 
 
357
 
 
358
    /**
 
359
     * Compare the specified object with this list for equality.  This
 
360
     * implementation uses exactly the code that is used to define the
 
361
     * list equals function in the documentation for the
 
362
     * <code>List.equals</code> method.
 
363
     *
 
364
     * @param o Object to be compared to this list
 
365
     */
 
366
    public boolean equals(Object o) {
 
367
 
 
368
        // Simple tests that require no synchronization
 
369
        if (o == this)
 
370
            return (true);
 
371
        else if (!(o instanceof List))
 
372
            return (false);
 
373
        List lo = (List) o;
 
374
 
 
375
        // Compare the sets of elements for equality
 
376
        if (fast) {
 
377
            ListIterator li1 = list.listIterator();
 
378
            ListIterator li2 = lo.listIterator();
 
379
            while (li1.hasNext() && li2.hasNext()) {
 
380
                Object o1 = li1.next();
 
381
                Object o2 = li2.next();
 
382
                if (!(o1 == null ? o2 == null : o1.equals(o2)))
 
383
                    return (false);
 
384
            }
 
385
            return (!(li1.hasNext() || li2.hasNext()));
 
386
        } else {
 
387
            synchronized (list) {
 
388
                ListIterator li1 = list.listIterator();
 
389
                ListIterator li2 = lo.listIterator();
 
390
                while (li1.hasNext() && li2.hasNext()) {
 
391
                    Object o1 = li1.next();
 
392
                    Object o2 = li2.next();
 
393
                    if (!(o1 == null ? o2 == null : o1.equals(o2)))
 
394
                        return (false);
 
395
                }
 
396
                return (!(li1.hasNext() || li2.hasNext()));
 
397
            }
 
398
        }
 
399
 
 
400
    }
 
401
 
 
402
 
 
403
    /**
 
404
     * Return the element at the specified position in the list.
 
405
     *
 
406
     * @param index The index of the element to return
 
407
     *
 
408
     * @exception IndexOutOfBoundsException if the index is out of range
 
409
     */
 
410
    public Object get(int index) {
 
411
 
 
412
        if (fast) {
 
413
            return (list.get(index));
 
414
        } else {
 
415
            synchronized (list) {
 
416
                return (list.get(index));
 
417
            }
 
418
        }
 
419
 
 
420
    }
 
421
 
 
422
 
 
423
    /**
 
424
     * Return the hash code value for this list.  This implementation uses
 
425
     * exactly the code that is used to define the list hash function in the
 
426
     * documentation for the <code>List.hashCode</code> method.
 
427
     */
 
428
    public int hashCode() {
 
429
 
 
430
        if (fast) {
 
431
            int hashCode = 1;
 
432
            java.util.Iterator i = list.iterator();
 
433
            while (i.hasNext()) {
 
434
                Object o = i.next();
 
435
                hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
 
436
            }
 
437
            return (hashCode);
 
438
        } else {
 
439
            synchronized (list) {
 
440
                int hashCode = 1;
 
441
                java.util.Iterator i = list.iterator();
 
442
                while (i.hasNext()) {
 
443
                    Object o = i.next();
 
444
                    hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
 
445
                }
 
446
                return (hashCode);
 
447
            }
 
448
        }
 
449
 
 
450
    }
 
451
 
 
452
 
 
453
    /**
 
454
     * Search for the first occurrence of the given argument, testing
 
455
     * for equality using the <code>equals()</code> method, and return
 
456
     * the corresponding index, or -1 if the object is not found.
 
457
     *
 
458
     * @param element The element to search for
 
459
     */
 
460
    public int indexOf(Object element) {
 
461
 
 
462
        if (fast) {
 
463
            return (list.indexOf(element));
 
464
        } else {
 
465
            synchronized (list) {
 
466
                return (list.indexOf(element));
 
467
            }
 
468
        }
 
469
 
 
470
    }
 
471
 
 
472
 
 
473
    /**
 
474
     * Test if this list has no elements.
 
475
     */
 
476
    public boolean isEmpty() {
 
477
 
 
478
        if (fast) {
 
479
            return (list.isEmpty());
 
480
        } else {
 
481
            synchronized (list) {
 
482
                return (list.isEmpty());
 
483
            }
 
484
        }
 
485
 
 
486
    }
 
487
 
 
488
 
 
489
    /**
 
490
     * Return an iterator over the elements in this list in proper sequence.
 
491
     * <br><br>
 
492
     * <strong>IMPLEMENTATION NOTE</strong> - If the list is operating in fast
 
493
     * mode, an Iterator is returned, and a structural modification to the
 
494
     * list is made, then the Iterator will continue over the previous contents
 
495
     * of the list (at the time that the Iterator was created), rather than
 
496
     * failing due to concurrent modifications.
 
497
     */
 
498
    public Iterator iterator() {
 
499
        if (fast) {
 
500
            return new ListIter(0);
 
501
        } else {
 
502
            return list.iterator();
 
503
        }
 
504
    }
 
505
 
 
506
 
 
507
    /**
 
508
     * Search for the last occurrence of the given argument, testing
 
509
     * for equality using the <code>equals()</code> method, and return
 
510
     * the corresponding index, or -1 if the object is not found.
 
511
     *
 
512
     * @param element The element to search for
 
513
     */
 
514
    public int lastIndexOf(Object element) {
 
515
 
 
516
        if (fast) {
 
517
            return (list.lastIndexOf(element));
 
518
        } else {
 
519
            synchronized (list) {
 
520
                return (list.lastIndexOf(element));
 
521
            }
 
522
        }
 
523
 
 
524
    }
 
525
 
 
526
 
 
527
    /**
 
528
     * Return an iterator of the elements of this list, in proper sequence.
 
529
     * See the implementation note on <code>iterator()</code>.
 
530
     */
 
531
    public ListIterator listIterator() {
 
532
        if (fast) {
 
533
            return new ListIter(0);
 
534
        } else {
 
535
            return list.listIterator();
 
536
        }
 
537
    }
 
538
 
 
539
 
 
540
    /**
 
541
     * Return an iterator of the elements of this list, in proper sequence,
 
542
     * starting at the specified position.
 
543
     * See the implementation note on <code>iterator()</code>.
 
544
     *
 
545
     * @param index The starting position of the iterator to return
 
546
     *
 
547
     * @exception IndexOutOfBoundsException if the index is out of range
 
548
     */
 
549
    public ListIterator listIterator(int index) {
 
550
        if (fast) {
 
551
            return new ListIter(index);
 
552
        } else {
 
553
            return list.listIterator(index);
 
554
        }
 
555
    }
 
556
 
 
557
 
 
558
    /**
 
559
     * Remove the element at the specified position in the list, and shift
 
560
     * any subsequent elements down one position.
 
561
     *
 
562
     * @param index Index of the element to be removed
 
563
     *
 
564
     * @exception IndexOutOfBoundsException if the index is out of range
 
565
     */
 
566
    public Object remove(int index) {
 
567
 
 
568
        if (fast) {
 
569
            synchronized (this) {
 
570
                ArrayList temp = (ArrayList) list.clone();
 
571
                Object result = temp.remove(index);
 
572
                list = temp;
 
573
                return (result);
 
574
            }
 
575
        } else {
 
576
            synchronized (list) {
 
577
                return (list.remove(index));
 
578
            }
 
579
        }
 
580
 
 
581
    }
 
582
 
 
583
 
 
584
    /**
 
585
     * Remove the first occurrence of the specified element from the list,
 
586
     * and shift any subsequent elements down one position.
 
587
     *
 
588
     * @param element Element to be removed
 
589
     */
 
590
    public boolean remove(Object element) {
 
591
 
 
592
        if (fast) {
 
593
            synchronized (this) {
 
594
                ArrayList temp = (ArrayList) list.clone();
 
595
                boolean result = temp.remove(element);
 
596
                list = temp;
 
597
                return (result);
 
598
            }
 
599
        } else {
 
600
            synchronized (list) {
 
601
                return (list.remove(element));
 
602
            }
 
603
        }
 
604
 
 
605
    }
 
606
 
 
607
 
 
608
    /**
 
609
     * Remove from this collection all of its elements that are contained
 
610
     * in the specified collection.
 
611
     *
 
612
     * @param collection Collection containing elements to be removed
 
613
     *
 
614
     * @exception UnsupportedOperationException if this optional operation
 
615
     *  is not supported by this list
 
616
     */
 
617
    public boolean removeAll(Collection collection) {
 
618
 
 
619
        if (fast) {
 
620
            synchronized (this) {
 
621
                ArrayList temp = (ArrayList) list.clone();
 
622
                boolean result = temp.removeAll(collection);
 
623
                list = temp;
 
624
                return (result);
 
625
            }
 
626
        } else {
 
627
            synchronized (list) {
 
628
                return (list.removeAll(collection));
 
629
            }
 
630
        }
 
631
 
 
632
    }
 
633
 
 
634
 
 
635
    /**
 
636
     * Remove from this collection all of its elements except those that are
 
637
     * contained in the specified collection.
 
638
     *
 
639
     * @param collection Collection containing elements to be retained
 
640
     *
 
641
     * @exception UnsupportedOperationException if this optional operation
 
642
     *  is not supported by this list
 
643
     */
 
644
    public boolean retainAll(Collection collection) {
 
645
 
 
646
        if (fast) {
 
647
            synchronized (this) {
 
648
                ArrayList temp = (ArrayList) list.clone();
 
649
                boolean result = temp.retainAll(collection);
 
650
                list = temp;
 
651
                return (result);
 
652
            }
 
653
        } else {
 
654
            synchronized (list) {
 
655
                return (list.retainAll(collection));
 
656
            }
 
657
        }
 
658
 
 
659
    }
 
660
 
 
661
 
 
662
    /**
 
663
     * Replace the element at the specified position in this list with
 
664
     * the specified element.  Returns the previous object at that position.
 
665
     * <br><br>
 
666
     * <strong>IMPLEMENTATION NOTE</strong> - This operation is specifically
 
667
     * documented to not be a structural change, so it is safe to be performed
 
668
     * without cloning.
 
669
     *
 
670
     * @param index Index of the element to replace
 
671
     * @param element The new element to be stored
 
672
     *
 
673
     * @exception IndexOutOfBoundsException if the index is out of range
 
674
     */
 
675
    public Object set(int index, Object element) {
 
676
 
 
677
        if (fast) {
 
678
            return (list.set(index, element));
 
679
        } else {
 
680
            synchronized (list) {
 
681
                return (list.set(index, element));
 
682
            }
 
683
        }
 
684
 
 
685
    }
 
686
 
 
687
 
 
688
    /**
 
689
     * Return the number of elements in this list.
 
690
     */
 
691
    public int size() {
 
692
 
 
693
        if (fast) {
 
694
            return (list.size());
 
695
        } else {
 
696
            synchronized (list) {
 
697
                return (list.size());
 
698
            }
 
699
        }
 
700
 
 
701
    }
 
702
 
 
703
 
 
704
    /**
 
705
     * Return a view of the portion of this list between fromIndex
 
706
     * (inclusive) and toIndex (exclusive).  The returned list is backed
 
707
     * by this list, so non-structural changes in the returned list are
 
708
     * reflected in this list.  The returned list supports
 
709
     * all of the optional list operations supported by this list.
 
710
     *
 
711
     * @param fromIndex The starting index of the sublist view
 
712
     * @param toIndex The index after the end of the sublist view
 
713
     *
 
714
     * @exception IndexOutOfBoundsException if an index is out of range
 
715
     */
 
716
    public List subList(int fromIndex, int toIndex) {
 
717
        if (fast) {
 
718
            return new SubList(fromIndex, toIndex);
 
719
        } else {
 
720
            return list.subList(fromIndex, toIndex);
 
721
        }
 
722
    }
 
723
 
 
724
 
 
725
    /**
 
726
     * Return an array containing all of the elements in this list in the
 
727
     * correct order.
 
728
     */
 
729
    public Object[] toArray() {
 
730
 
 
731
        if (fast) {
 
732
            return (list.toArray());
 
733
        } else {
 
734
            synchronized (list) {
 
735
                return (list.toArray());
 
736
            }
 
737
        }
 
738
 
 
739
    }
 
740
 
 
741
 
 
742
    /**
 
743
     * Return an array containing all of the elements in this list in the
 
744
     * correct order.  The runtime type of the returned array is that of
 
745
     * the specified array.  If the list fits in the specified array, it is
 
746
     * returned therein.  Otherwise, a new array is allocated with the
 
747
     * runtime type of the specified array, and the size of this list.
 
748
     *
 
749
     * @param array Array defining the element type of the returned list
 
750
     *
 
751
     * @exception ArrayStoreException if the runtime type of <code>array</code>
 
752
     *  is not a supertype of the runtime type of every element in this list
 
753
     */
 
754
    public Object[] toArray(Object array[]) {
 
755
 
 
756
        if (fast) {
 
757
            return (list.toArray(array));
 
758
        } else {
 
759
            synchronized (list) {
 
760
                return (list.toArray(array));
 
761
            }
 
762
        }
 
763
 
 
764
    }
 
765
 
 
766
 
 
767
    /**
 
768
     * Return a String representation of this object.
 
769
     */
 
770
    public String toString() {
 
771
 
 
772
        StringBuffer sb = new StringBuffer("FastArrayList[");
 
773
        sb.append(list.toString());
 
774
        sb.append("]");
 
775
        return (sb.toString());
 
776
 
 
777
    }
 
778
 
 
779
 
 
780
    /**
 
781
     * Trim the capacity of this <code>ArrayList</code> instance to be the
 
782
     * list's current size.  An application can use this operation to minimize
 
783
     * the storage of an <code>ArrayList</code> instance.
 
784
     */
 
785
    public void trimToSize() {
 
786
 
 
787
        if (fast) {
 
788
            synchronized (this) {
 
789
                ArrayList temp = (ArrayList) list.clone();
 
790
                temp.trimToSize();
 
791
                list = temp;
 
792
            }
 
793
        } else {
 
794
            synchronized (list) {
 
795
                list.trimToSize();
 
796
            }
 
797
        }
 
798
 
 
799
    }
 
800
 
 
801
 
 
802
 
 
803
    private class SubList implements List {
 
804
 
 
805
        private int first;
 
806
        private int last;
 
807
        private List expected;
 
808
 
 
809
 
 
810
        public SubList(int first, int last) {
 
811
            this.first = first;
 
812
            this.last = last;
 
813
            this.expected = list;
 
814
        }
 
815
 
 
816
        private List get(List l) {
 
817
            if (list != expected) {
 
818
                throw new ConcurrentModificationException();
 
819
            }
 
820
            return l.subList(first, last);
 
821
        }
 
822
 
 
823
        public void clear() {
 
824
            if (fast) {
 
825
                synchronized (FastArrayList.this) {
 
826
                    ArrayList temp = (ArrayList) list.clone();
 
827
                    get(temp).clear();
 
828
                    last = first;
 
829
                    list = temp;
 
830
                    expected = temp;
 
831
                }
 
832
            } else {
 
833
                synchronized (list) {
 
834
                    get(expected).clear();
 
835
                }
 
836
            }
 
837
        }
 
838
 
 
839
        public boolean remove(Object o) {
 
840
            if (fast) {
 
841
                synchronized (FastArrayList.this) {
 
842
                    ArrayList temp = (ArrayList) list.clone();
 
843
                    boolean r = get(temp).remove(o);
 
844
                    if (r) last--;
 
845
                    list = temp;
 
846
                    expected = temp;
 
847
                    return r;
 
848
                }
 
849
            } else {
 
850
                synchronized (list) {
 
851
                    return get(expected).remove(o);
 
852
                }
 
853
            }
 
854
        }
 
855
 
 
856
        public boolean removeAll(Collection o) {
 
857
            if (fast) {
 
858
                synchronized (FastArrayList.this) {
 
859
                    ArrayList temp = (ArrayList) list.clone();
 
860
                    List sub = get(temp);
 
861
                    boolean r = sub.removeAll(o);
 
862
                    if (r) last = first + sub.size();
 
863
                    list = temp;
 
864
                    expected = temp;
 
865
                    return r;
 
866
                }
 
867
            } else {
 
868
                synchronized (list) {
 
869
                    return get(expected).removeAll(o);
 
870
                }
 
871
            }
 
872
        }
 
873
 
 
874
        public boolean retainAll(Collection o) {
 
875
            if (fast) {
 
876
                synchronized (FastArrayList.this) {
 
877
                    ArrayList temp = (ArrayList) list.clone();
 
878
                    List sub = get(temp);
 
879
                    boolean r = sub.retainAll(o);
 
880
                    if (r) last = first + sub.size();
 
881
                    list = temp;
 
882
                    expected = temp;
 
883
                    return r;
 
884
                }
 
885
            } else {
 
886
                synchronized (list) {
 
887
                    return get(expected).retainAll(o);
 
888
                }
 
889
            }
 
890
        }
 
891
 
 
892
        public int size() {
 
893
            if (fast) {
 
894
                return get(expected).size();
 
895
            } else {
 
896
                synchronized (list) {
 
897
                    return get(expected).size();
 
898
                }
 
899
            }
 
900
        }
 
901
 
 
902
 
 
903
        public boolean isEmpty() {
 
904
            if (fast) {
 
905
                return get(expected).isEmpty();
 
906
            } else {
 
907
                synchronized (list) {
 
908
                    return get(expected).isEmpty();
 
909
                }
 
910
            }
 
911
        }
 
912
 
 
913
        public boolean contains(Object o) {
 
914
            if (fast) {
 
915
                return get(expected).contains(o);
 
916
            } else {
 
917
                synchronized (list) {
 
918
                    return get(expected).contains(o);
 
919
                }
 
920
            }
 
921
        }
 
922
 
 
923
        public boolean containsAll(Collection o) {
 
924
            if (fast) {
 
925
                return get(expected).containsAll(o);
 
926
            } else {
 
927
                synchronized (list) {
 
928
                    return get(expected).containsAll(o);
 
929
                }
 
930
            }
 
931
        }
 
932
 
 
933
        public Object[] toArray(Object[] o) {
 
934
            if (fast) {
 
935
                return get(expected).toArray(o);
 
936
            } else {
 
937
                synchronized (list) {
 
938
                    return get(expected).toArray(o);
 
939
                }
 
940
            }
 
941
        }
 
942
 
 
943
        public Object[] toArray() {
 
944
            if (fast) {
 
945
                return get(expected).toArray();
 
946
            } else {
 
947
                synchronized (list) {
 
948
                    return get(expected).toArray();
 
949
                }
 
950
            }
 
951
        }
 
952
 
 
953
 
 
954
        public boolean equals(Object o) {
 
955
            if (o == this) return true;
 
956
            if (fast) {
 
957
                return get(expected).equals(o);
 
958
            } else {
 
959
                synchronized (list) {
 
960
                    return get(expected).equals(o);
 
961
                }
 
962
            }
 
963
        }
 
964
 
 
965
        public int hashCode() {
 
966
            if (fast) {
 
967
                return get(expected).hashCode();
 
968
            } else {
 
969
                synchronized (list) {
 
970
                    return get(expected).hashCode();
 
971
                }
 
972
            }
 
973
        }
 
974
 
 
975
        public boolean add(Object o) {
 
976
            if (fast) {
 
977
                synchronized (FastArrayList.this) {
 
978
                    ArrayList temp = (ArrayList) list.clone();
 
979
                    boolean r = get(temp).add(o);
 
980
                    if (r) last++;
 
981
                    list = temp;
 
982
                    expected = temp;
 
983
                    return r;
 
984
                }
 
985
            } else {
 
986
                synchronized (list) {
 
987
                    return get(expected).add(o);
 
988
                }
 
989
            }
 
990
        }
 
991
 
 
992
        public boolean addAll(Collection o) {
 
993
            if (fast) {
 
994
                synchronized (FastArrayList.this) {
 
995
                    ArrayList temp = (ArrayList) list.clone();
 
996
                    boolean r = get(temp).addAll(o);
 
997
                    if (r) last += o.size();
 
998
                    list = temp;
 
999
                    expected = temp;
 
1000
                    return r;
 
1001
                }
 
1002
            } else {
 
1003
                synchronized (list) {
 
1004
                    return get(expected).addAll(o);
 
1005
                }
 
1006
            }
 
1007
        }
 
1008
 
 
1009
        public void add(int i, Object o) {
 
1010
            if (fast) {
 
1011
                synchronized (FastArrayList.this) {
 
1012
                    ArrayList temp = (ArrayList) list.clone();
 
1013
                    get(temp).add(i, o);
 
1014
                    last++;
 
1015
                    list = temp;
 
1016
                    expected = temp;
 
1017
                }
 
1018
            } else {
 
1019
                synchronized (list) {
 
1020
                    get(expected).add(i, o);
 
1021
                }
 
1022
            }
 
1023
        }
 
1024
 
 
1025
        public boolean addAll(int i, Collection o) {
 
1026
            if (fast) {
 
1027
                synchronized (FastArrayList.this) {
 
1028
                    ArrayList temp = (ArrayList) list.clone();
 
1029
                    boolean r = get(temp).addAll(i, o);
 
1030
                    list = temp;
 
1031
                    if (r) last += o.size();
 
1032
                    expected = temp;
 
1033
                    return r;
 
1034
                }
 
1035
            } else {
 
1036
                synchronized (list) {
 
1037
                    return get(expected).addAll(i, o);
 
1038
                }
 
1039
            }
 
1040
        }
 
1041
 
 
1042
        public Object remove(int i) {
 
1043
            if (fast) {
 
1044
                synchronized (FastArrayList.this) {
 
1045
                    ArrayList temp = (ArrayList) list.clone();
 
1046
                    Object o = get(temp).remove(i);
 
1047
                    last--;
 
1048
                    list = temp;
 
1049
                    expected = temp;
 
1050
                    return o;
 
1051
                }
 
1052
            } else {
 
1053
                synchronized (list) {
 
1054
                    return get(expected).remove(i);
 
1055
                }
 
1056
            }
 
1057
        }
 
1058
 
 
1059
        public Object set(int i, Object a) {
 
1060
            if (fast) {
 
1061
                synchronized (FastArrayList.this) {
 
1062
                    ArrayList temp = (ArrayList) list.clone();
 
1063
                    Object o = get(temp).set(i, a);
 
1064
                    list = temp;
 
1065
                    expected = temp;
 
1066
                    return o;
 
1067
                }
 
1068
            } else {
 
1069
                synchronized (list) {
 
1070
                    return get(expected).set(i, a);
 
1071
                }
 
1072
            }
 
1073
        }
 
1074
 
 
1075
 
 
1076
        public Iterator iterator() {
 
1077
            return new SubListIter(0);
 
1078
        }
 
1079
 
 
1080
        public ListIterator listIterator() {
 
1081
            return new SubListIter(0);
 
1082
        }
 
1083
 
 
1084
        public ListIterator listIterator(int i) {
 
1085
            return new SubListIter(i);
 
1086
        }
 
1087
 
 
1088
 
 
1089
        public Object get(int i) {
 
1090
            if (fast) {
 
1091
                return get(expected).get(i);
 
1092
            } else {
 
1093
                synchronized (list) {
 
1094
                    return get(expected).get(i);
 
1095
                }
 
1096
            }
 
1097
        }
 
1098
 
 
1099
        public int indexOf(Object o) {
 
1100
            if (fast) {
 
1101
                return get(expected).indexOf(o);
 
1102
            } else {
 
1103
                synchronized (list) {
 
1104
                    return get(expected).indexOf(o);
 
1105
                }
 
1106
            }
 
1107
        }
 
1108
 
 
1109
 
 
1110
        public int lastIndexOf(Object o) {
 
1111
            if (fast) {
 
1112
                return get(expected).lastIndexOf(o);
 
1113
            } else {
 
1114
                synchronized (list) {
 
1115
                    return get(expected).lastIndexOf(o);
 
1116
                }
 
1117
            }
 
1118
        }
 
1119
 
 
1120
 
 
1121
        public List subList(int f, int l) {
 
1122
            if (list != expected) {
 
1123
                throw new ConcurrentModificationException();
 
1124
            }
 
1125
            return new SubList(first + f, f + l);
 
1126
        }
 
1127
 
 
1128
 
 
1129
    private class SubListIter implements ListIterator {
 
1130
 
 
1131
        private List expected;
 
1132
        private ListIterator iter;
 
1133
        private int lastReturnedIndex = -1;
 
1134
 
 
1135
 
 
1136
        public SubListIter(int i) {
 
1137
            this.expected = list;
 
1138
            this.iter = SubList.this.get(expected).listIterator(i);
 
1139
        }
 
1140
 
 
1141
        private void checkMod() {
 
1142
            if (list != expected) {
 
1143
                throw new ConcurrentModificationException();
 
1144
            }
 
1145
        }
 
1146
 
 
1147
        List get() {
 
1148
            return SubList.this.get(expected);
 
1149
        }
 
1150
 
 
1151
        public boolean hasNext() {
 
1152
            checkMod();
 
1153
            return iter.hasNext();     
 
1154
        }
 
1155
 
 
1156
        public Object next() {
 
1157
            checkMod();
 
1158
            lastReturnedIndex = iter.nextIndex();
 
1159
            return iter.next();
 
1160
        }
 
1161
 
 
1162
        public boolean hasPrevious() {
 
1163
            checkMod();
 
1164
            return iter.hasPrevious();
 
1165
        }
 
1166
 
 
1167
        public Object previous() {
 
1168
            checkMod();
 
1169
            lastReturnedIndex = iter.previousIndex();
 
1170
            return iter.previous();
 
1171
        }
 
1172
 
 
1173
        public int previousIndex() {
 
1174
            checkMod();
 
1175
            return iter.previousIndex();
 
1176
        }
 
1177
 
 
1178
        public int nextIndex() {
 
1179
            checkMod();
 
1180
            return iter.nextIndex();
 
1181
        }
 
1182
 
 
1183
        public void remove() {
 
1184
            checkMod();
 
1185
            if (lastReturnedIndex < 0) {
 
1186
                throw new IllegalStateException();
 
1187
            }
 
1188
            get().remove(lastReturnedIndex);
 
1189
            last--;
 
1190
            expected = list;
 
1191
            iter = get().listIterator(previousIndex());
 
1192
            lastReturnedIndex = -1;
 
1193
        }
 
1194
 
 
1195
        public void set(Object o) {
 
1196
            checkMod();
 
1197
            if (lastReturnedIndex < 0) {
 
1198
                throw new IllegalStateException();
 
1199
            }
 
1200
            get().set(lastReturnedIndex, o);
 
1201
            expected = list;
 
1202
            iter = get().listIterator(previousIndex() + 1);
 
1203
        } 
 
1204
 
 
1205
        public void add(Object o) {
 
1206
            checkMod();
 
1207
            int i = nextIndex();
 
1208
            get().add(i, o);
 
1209
            last++;
 
1210
            iter = get().listIterator(i + 1);
 
1211
            lastReturnedIndex = 1;
 
1212
        }
 
1213
 
 
1214
   }
 
1215
 
 
1216
 
 
1217
    }
 
1218
 
 
1219
 
 
1220
 
 
1221
    private class ListIter implements ListIterator {
 
1222
 
 
1223
        private List expected;
 
1224
        private ListIterator iter;
 
1225
        private int lastReturnedIndex = -1;
 
1226
 
 
1227
 
 
1228
        public ListIter(int i) {
 
1229
            this.expected = list;
 
1230
            this.iter = get().listIterator(i);
 
1231
        }
 
1232
 
 
1233
        private void checkMod() {
 
1234
            if (list != expected) {
 
1235
                throw new ConcurrentModificationException();
 
1236
            }
 
1237
        }
 
1238
 
 
1239
        List get() {
 
1240
            return expected;
 
1241
        }
 
1242
 
 
1243
        public boolean hasNext() {
 
1244
            checkMod();
 
1245
            return iter.hasNext();     
 
1246
        }
 
1247
 
 
1248
        public Object next() {
 
1249
            checkMod();
 
1250
            lastReturnedIndex = iter.nextIndex();
 
1251
            return iter.next();
 
1252
        }
 
1253
 
 
1254
        public boolean hasPrevious() {
 
1255
            checkMod();
 
1256
            return iter.hasPrevious();
 
1257
        }
 
1258
 
 
1259
        public Object previous() {
 
1260
            checkMod();
 
1261
            lastReturnedIndex = iter.previousIndex();
 
1262
            return iter.previous();
 
1263
        }
 
1264
 
 
1265
        public int previousIndex() {
 
1266
            checkMod();
 
1267
            return iter.previousIndex();
 
1268
        }
 
1269
 
 
1270
        public int nextIndex() {
 
1271
            checkMod();
 
1272
            return iter.nextIndex();
 
1273
        }
 
1274
 
 
1275
        public void remove() {
 
1276
            checkMod();
 
1277
            if (lastReturnedIndex < 0) {
 
1278
                throw new IllegalStateException();
 
1279
            }
 
1280
            get().remove(lastReturnedIndex);
 
1281
            expected = list;
 
1282
            iter = get().listIterator(previousIndex());
 
1283
            lastReturnedIndex = -1;
 
1284
        }
 
1285
 
 
1286
        public void set(Object o) {
 
1287
            checkMod();
 
1288
            if (lastReturnedIndex < 0) {
 
1289
                throw new IllegalStateException();
 
1290
            }
 
1291
            get().set(lastReturnedIndex, o);
 
1292
            expected = list;
 
1293
            iter = get().listIterator(previousIndex() + 1);
 
1294
        } 
 
1295
 
 
1296
        public void add(Object o) {
 
1297
            checkMod();
 
1298
            int i = nextIndex();
 
1299
            get().add(i, o);
 
1300
            iter = get().listIterator(i + 1);
 
1301
            lastReturnedIndex = 1;
 
1302
        }
 
1303
 
 
1304
   }
 
1305
}