KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > FastArrayList


1 /*
2  * Copyright 2001-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 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.ConcurrentModificationException JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.ListIterator JavaDoc;
24
25 /**
26  * <p>A customized implementation of <code>java.util.ArrayList</code> designed
27  * to operate in a multithreaded environment where the large majority of
28  * method calls are read-only, instead of structural changes. When operating
29  * in "fast" mode, read calls are non-synchronized and write calls perform the
30  * following steps:</p>
31  * <ul>
32  * <li>Clone the existing collection
33  * <li>Perform the modification on the clone
34  * <li>Replace the existing collection with the (modified) clone
35  * </ul>
36  * <p>When first created, objects of this class default to "slow" mode, where
37  * all accesses of any type are synchronized but no cloning takes place. This
38  * is appropriate for initially populating the collection, followed by a switch
39  * to "fast" mode (by calling <code>setFast(true)</code>) after initialization
40  * is complete.</p>
41  *
42  * <p><strong>NOTE</strong>: If you are creating and accessing an
43  * <code>ArrayList</code> only within a single thread, you should use
44  * <code>java.util.ArrayList</code> directly (with no synchronization), for
45  * maximum performance.</p>
46  *
47  * <p><strong>NOTE</strong>: <i>This class is not cross-platform.
48  * Using it may cause unexpected failures on some architectures.</i>
49  * It suffers from the same problems as the double-checked locking idiom.
50  * In particular, the instruction that clones the internal collection and the
51  * instruction that sets the internal reference to the clone can be executed
52  * or perceived out-of-order. This means that any read operation might fail
53  * unexpectedly, as it may be reading the state of the internal collection
54  * before the internal collection is fully formed.
55  * For more information on the double-checked locking idiom, see the
56  * <a HREF="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html">
57  * Double-Checked Locking Idiom Is Broken Declaration</a>.</p>
58  *
59  * @since Commons Collections 1.0
60  * @version $Revision: 1.15 $ $Date: 2004/02/18 01:15:42 $
61  *
62  * @author Craig R. McClanahan
63  */

64 public class FastArrayList extends ArrayList JavaDoc {
65
66
67     // ----------------------------------------------------------- Constructors
68

69
70     /**
71      * Construct a an empty list.
72      */

73     public FastArrayList() {
74
75         super();
76         this.list = new ArrayList JavaDoc();
77
78     }
79
80
81     /**
82      * Construct an empty list with the specified capacity.
83      *
84      * @param capacity The initial capacity of the empty list
85      */

86     public FastArrayList(int capacity) {
87
88         super();
89         this.list = new ArrayList JavaDoc(capacity);
90
91     }
92
93
94     /**
95      * Construct a list containing the elements of the specified collection,
96      * in the order they are returned by the collection's iterator.
97      *
98      * @param collection The collection whose elements initialize the contents
99      * of this list
100      */

101     public FastArrayList(Collection JavaDoc collection) {
102
103         super();
104         this.list = new ArrayList JavaDoc(collection);
105
106     }
107
108
109     // ----------------------------------------------------- Instance Variables
110

111
112     /**
113      * The underlying list we are managing.
114      */

115     protected ArrayList JavaDoc list = null;
116
117
118     // ------------------------------------------------------------- Properties
119

120
121     /**
122      * Are we operating in "fast" mode?
123      */

124     protected boolean fast = false;
125
126
127     /**
128      * Returns true if this list is operating in fast mode.
129      *
130      * @return true if this list is operating in fast mode
131      */

132     public boolean getFast() {
133         return (this.fast);
134     }
135
136     /**
137      * Sets whether this list will operate in fast mode.
138      *
139      * @param fast true if the list should operate in fast mode
140      */

141     public void setFast(boolean fast) {
142         this.fast = fast;
143     }
144
145
146     // --------------------------------------------------------- Public Methods
147

148
149     /**
150      * Appends the specified element to the end of this list.
151      *
152      * @param element The element to be appended
153      */

154     public boolean add(Object JavaDoc element) {
155
156         if (fast) {
157             synchronized (this) {
158                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
159                 boolean result = temp.add(element);
160                 list = temp;
161                 return (result);
162             }
163         } else {
164             synchronized (list) {
165                 return (list.add(element));
166             }
167         }
168
169     }
170
171
172     /**
173      * Insert the specified element at the specified position in this list,
174      * and shift all remaining elements up one position.
175      *
176      * @param index Index at which to insert this element
177      * @param element The element to be inserted
178      *
179      * @exception IndexOutOfBoundsException if the index is out of range
180      */

181     public void add(int index, Object JavaDoc element) {
182
183         if (fast) {
184             synchronized (this) {
185                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
186                 temp.add(index, element);
187                 list = temp;
188             }
189         } else {
190             synchronized (list) {
191                 list.add(index, element);
192             }
193         }
194
195     }
196
197
198     /**
199      * Append all of the elements in the specified Collection to the end
200      * of this list, in the order that they are returned by the specified
201      * Collection's Iterator.
202      *
203      * @param collection The collection to be appended
204      */

205     public boolean addAll(Collection JavaDoc collection) {
206
207         if (fast) {
208             synchronized (this) {
209                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
210                 boolean result = temp.addAll(collection);
211                 list = temp;
212                 return (result);
213             }
214         } else {
215             synchronized (list) {
216                 return (list.addAll(collection));
217             }
218         }
219
220     }
221
222
223     /**
224      * Insert all of the elements in the specified Collection at the specified
225      * position in this list, and shift any previous elements upwards as
226      * needed.
227      *
228      * @param index Index at which insertion takes place
229      * @param collection The collection to be added
230      *
231      * @exception IndexOutOfBoundsException if the index is out of range
232      */

233     public boolean addAll(int index, Collection JavaDoc collection) {
234
235         if (fast) {
236             synchronized (this) {
237                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
238                 boolean result = temp.addAll(index, collection);
239                 list = temp;
240                 return (result);
241             }
242         } else {
243             synchronized (list) {
244                 return (list.addAll(index, collection));
245             }
246         }
247
248     }
249
250
251     /**
252      * Remove all of the elements from this list. The list will be empty
253      * after this call returns.
254      *
255      * @exception UnsupportedOperationException if <code>clear()</code>
256      * is not supported by this list
257      */

258     public void clear() {
259
260         if (fast) {
261             synchronized (this) {
262                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
263                 temp.clear();
264                 list = temp;
265             }
266         } else {
267             synchronized (list) {
268                 list.clear();
269             }
270         }
271
272     }
273
274
275     /**
276      * Return a shallow copy of this <code>FastArrayList</code> instance.
277      * The elements themselves are not copied.
278      */

279     public Object JavaDoc clone() {
280
281         FastArrayList results = null;
282         if (fast) {
283             results = new FastArrayList(list);
284         } else {
285             synchronized (list) {
286                 results = new FastArrayList(list);
287             }
288         }
289         results.setFast(getFast());
290         return (results);
291
292     }
293
294
295     /**
296      * Return <code>true</code> if this list contains the specified element.
297      *
298      * @param element The element to test for
299      */

300     public boolean contains(Object JavaDoc element) {
301
302         if (fast) {
303             return (list.contains(element));
304         } else {
305             synchronized (list) {
306                 return (list.contains(element));
307             }
308         }
309
310     }
311
312
313     /**
314      * Return <code>true</code> if this list contains all of the elements
315      * in the specified Collection.
316      *
317      * @param collection Collection whose elements are to be checked
318      */

319     public boolean containsAll(Collection JavaDoc collection) {
320
321         if (fast) {
322             return (list.containsAll(collection));
323         } else {
324             synchronized (list) {
325                 return (list.containsAll(collection));
326             }
327         }
328
329     }
330
331
332     /**
333      * Increase the capacity of this <code>ArrayList</code> instance, if
334      * necessary, to ensure that it can hold at least the number of elements
335      * specified by the minimum capacity argument.
336      *
337      * @param capacity The new minimum capacity
338      */

339     public void ensureCapacity(int capacity) {
340
341         if (fast) {
342             synchronized (this) {
343                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
344                 temp.ensureCapacity(capacity);
345                 list = temp;
346             }
347         } else {
348             synchronized (list) {
349                 list.ensureCapacity(capacity);
350             }
351         }
352
353     }
354
355
356     /**
357      * Compare the specified object with this list for equality. This
358      * implementation uses exactly the code that is used to define the
359      * list equals function in the documentation for the
360      * <code>List.equals</code> method.
361      *
362      * @param o Object to be compared to this list
363      */

364     public boolean equals(Object JavaDoc o) {
365
366         // Simple tests that require no synchronization
367
if (o == this)
368             return (true);
369         else if (!(o instanceof List JavaDoc))
370             return (false);
371         List JavaDoc lo = (List JavaDoc) o;
372
373         // Compare the sets of elements for equality
374
if (fast) {
375             ListIterator JavaDoc li1 = list.listIterator();
376             ListIterator JavaDoc li2 = lo.listIterator();
377             while (li1.hasNext() && li2.hasNext()) {
378                 Object JavaDoc o1 = li1.next();
379                 Object JavaDoc o2 = li2.next();
380                 if (!(o1 == null ? o2 == null : o1.equals(o2)))
381                     return (false);
382             }
383             return (!(li1.hasNext() || li2.hasNext()));
384         } else {
385             synchronized (list) {
386                 ListIterator JavaDoc li1 = list.listIterator();
387                 ListIterator JavaDoc li2 = lo.listIterator();
388                 while (li1.hasNext() && li2.hasNext()) {
389                     Object JavaDoc o1 = li1.next();
390                     Object JavaDoc o2 = li2.next();
391                     if (!(o1 == null ? o2 == null : o1.equals(o2)))
392                         return (false);
393                 }
394                 return (!(li1.hasNext() || li2.hasNext()));
395             }
396         }
397
398     }
399
400
401     /**
402      * Return the element at the specified position in the list.
403      *
404      * @param index The index of the element to return
405      *
406      * @exception IndexOutOfBoundsException if the index is out of range
407      */

408     public Object JavaDoc get(int index) {
409
410         if (fast) {
411             return (list.get(index));
412         } else {
413             synchronized (list) {
414                 return (list.get(index));
415             }
416         }
417
418     }
419
420
421     /**
422      * Return the hash code value for this list. This implementation uses
423      * exactly the code that is used to define the list hash function in the
424      * documentation for the <code>List.hashCode</code> method.
425      */

426     public int hashCode() {
427
428         if (fast) {
429             int hashCode = 1;
430             java.util.Iterator JavaDoc i = list.iterator();
431             while (i.hasNext()) {
432                 Object JavaDoc o = i.next();
433                 hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
434             }
435             return (hashCode);
436         } else {
437             synchronized (list) {
438                 int hashCode = 1;
439                 java.util.Iterator JavaDoc i = list.iterator();
440                 while (i.hasNext()) {
441                     Object JavaDoc o = i.next();
442                     hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
443                 }
444                 return (hashCode);
445             }
446         }
447
448     }
449
450
451     /**
452      * Search for the first occurrence of the given argument, testing
453      * for equality using the <code>equals()</code> method, and return
454      * the corresponding index, or -1 if the object is not found.
455      *
456      * @param element The element to search for
457      */

458     public int indexOf(Object JavaDoc element) {
459
460         if (fast) {
461             return (list.indexOf(element));
462         } else {
463             synchronized (list) {
464                 return (list.indexOf(element));
465             }
466         }
467
468     }
469
470
471     /**
472      * Test if this list has no elements.
473      */

474     public boolean isEmpty() {
475
476         if (fast) {
477             return (list.isEmpty());
478         } else {
479             synchronized (list) {
480                 return (list.isEmpty());
481             }
482         }
483
484     }
485
486
487     /**
488      * Return an iterator over the elements in this list in proper sequence.
489      * <br><br>
490      * <strong>IMPLEMENTATION NOTE</strong> - If the list is operating in fast
491      * mode, an Iterator is returned, and a structural modification to the
492      * list is made, then the Iterator will continue over the previous contents
493      * of the list (at the time that the Iterator was created), rather than
494      * failing due to concurrent modifications.
495      */

496     public Iterator JavaDoc iterator() {
497         if (fast) {
498             return new ListIter(0);
499         } else {
500             return list.iterator();
501         }
502     }
503
504
505     /**
506      * Search for the last occurrence of the given argument, testing
507      * for equality using the <code>equals()</code> method, and return
508      * the corresponding index, or -1 if the object is not found.
509      *
510      * @param element The element to search for
511      */

512     public int lastIndexOf(Object JavaDoc element) {
513
514         if (fast) {
515             return (list.lastIndexOf(element));
516         } else {
517             synchronized (list) {
518                 return (list.lastIndexOf(element));
519             }
520         }
521
522     }
523
524
525     /**
526      * Return an iterator of the elements of this list, in proper sequence.
527      * See the implementation note on <code>iterator()</code>.
528      */

529     public ListIterator JavaDoc listIterator() {
530         if (fast) {
531             return new ListIter(0);
532         } else {
533             return list.listIterator();
534         }
535     }
536
537
538     /**
539      * Return an iterator of the elements of this list, in proper sequence,
540      * starting at the specified position.
541      * See the implementation note on <code>iterator()</code>.
542      *
543      * @param index The starting position of the iterator to return
544      *
545      * @exception IndexOutOfBoundsException if the index is out of range
546      */

547     public ListIterator JavaDoc listIterator(int index) {
548         if (fast) {
549             return new ListIter(index);
550         } else {
551             return list.listIterator(index);
552         }
553     }
554
555
556     /**
557      * Remove the element at the specified position in the list, and shift
558      * any subsequent elements down one position.
559      *
560      * @param index Index of the element to be removed
561      *
562      * @exception IndexOutOfBoundsException if the index is out of range
563      */

564     public Object JavaDoc remove(int index) {
565
566         if (fast) {
567             synchronized (this) {
568                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
569                 Object JavaDoc result = temp.remove(index);
570                 list = temp;
571                 return (result);
572             }
573         } else {
574             synchronized (list) {
575                 return (list.remove(index));
576             }
577         }
578
579     }
580
581
582     /**
583      * Remove the first occurrence of the specified element from the list,
584      * and shift any subsequent elements down one position.
585      *
586      * @param element Element to be removed
587      */

588     public boolean remove(Object JavaDoc element) {
589
590         if (fast) {
591             synchronized (this) {
592                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
593                 boolean result = temp.remove(element);
594                 list = temp;
595                 return (result);
596             }
597         } else {
598             synchronized (list) {
599                 return (list.remove(element));
600             }
601         }
602
603     }
604
605
606     /**
607      * Remove from this collection all of its elements that are contained
608      * in the specified collection.
609      *
610      * @param collection Collection containing elements to be removed
611      *
612      * @exception UnsupportedOperationException if this optional operation
613      * is not supported by this list
614      */

615     public boolean removeAll(Collection JavaDoc collection) {
616
617         if (fast) {
618             synchronized (this) {
619                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
620                 boolean result = temp.removeAll(collection);
621                 list = temp;
622                 return (result);
623             }
624         } else {
625             synchronized (list) {
626                 return (list.removeAll(collection));
627             }
628         }
629
630     }
631
632
633     /**
634      * Remove from this collection all of its elements except those that are
635      * contained in the specified collection.
636      *
637      * @param collection Collection containing elements to be retained
638      *
639      * @exception UnsupportedOperationException if this optional operation
640      * is not supported by this list
641      */

642     public boolean retainAll(Collection JavaDoc collection) {
643
644         if (fast) {
645             synchronized (this) {
646                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
647                 boolean result = temp.retainAll(collection);
648                 list = temp;
649                 return (result);
650             }
651         } else {
652             synchronized (list) {
653                 return (list.retainAll(collection));
654             }
655         }
656
657     }
658
659
660     /**
661      * Replace the element at the specified position in this list with
662      * the specified element. Returns the previous object at that position.
663      * <br><br>
664      * <strong>IMPLEMENTATION NOTE</strong> - This operation is specifically
665      * documented to not be a structural change, so it is safe to be performed
666      * without cloning.
667      *
668      * @param index Index of the element to replace
669      * @param element The new element to be stored
670      *
671      * @exception IndexOutOfBoundsException if the index is out of range
672      */

673     public Object JavaDoc set(int index, Object JavaDoc element) {
674
675         if (fast) {
676             return (list.set(index, element));
677         } else {
678             synchronized (list) {
679                 return (list.set(index, element));
680             }
681         }
682
683     }
684
685
686     /**
687      * Return the number of elements in this list.
688      */

689     public int size() {
690
691         if (fast) {
692             return (list.size());
693         } else {
694             synchronized (list) {
695                 return (list.size());
696             }
697         }
698
699     }
700
701
702     /**
703      * Return a view of the portion of this list between fromIndex
704      * (inclusive) and toIndex (exclusive). The returned list is backed
705      * by this list, so non-structural changes in the returned list are
706      * reflected in this list. The returned list supports
707      * all of the optional list operations supported by this list.
708      *
709      * @param fromIndex The starting index of the sublist view
710      * @param toIndex The index after the end of the sublist view
711      *
712      * @exception IndexOutOfBoundsException if an index is out of range
713      */

714     public List JavaDoc subList(int fromIndex, int toIndex) {
715         if (fast) {
716             return new SubList(fromIndex, toIndex);
717         } else {
718             return list.subList(fromIndex, toIndex);
719         }
720     }
721
722
723     /**
724      * Return an array containing all of the elements in this list in the
725      * correct order.
726      */

727     public Object JavaDoc[] toArray() {
728
729         if (fast) {
730             return (list.toArray());
731         } else {
732             synchronized (list) {
733                 return (list.toArray());
734             }
735         }
736
737     }
738
739
740     /**
741      * Return an array containing all of the elements in this list in the
742      * correct order. The runtime type of the returned array is that of
743      * the specified array. If the list fits in the specified array, it is
744      * returned therein. Otherwise, a new array is allocated with the
745      * runtime type of the specified array, and the size of this list.
746      *
747      * @param array Array defining the element type of the returned list
748      *
749      * @exception ArrayStoreException if the runtime type of <code>array</code>
750      * is not a supertype of the runtime type of every element in this list
751      */

752     public Object JavaDoc[] toArray(Object JavaDoc array[]) {
753
754         if (fast) {
755             return (list.toArray(array));
756         } else {
757             synchronized (list) {
758                 return (list.toArray(array));
759             }
760         }
761
762     }
763
764
765     /**
766      * Return a String representation of this object.
767      */

768     public String JavaDoc toString() {
769
770         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("FastArrayList[");
771         sb.append(list.toString());
772         sb.append("]");
773         return (sb.toString());
774
775     }
776
777
778     /**
779      * Trim the capacity of this <code>ArrayList</code> instance to be the
780      * list's current size. An application can use this operation to minimize
781      * the storage of an <code>ArrayList</code> instance.
782      */

783     public void trimToSize() {
784
785         if (fast) {
786             synchronized (this) {
787                 ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
788                 temp.trimToSize();
789                 list = temp;
790             }
791         } else {
792             synchronized (list) {
793                 list.trimToSize();
794             }
795         }
796
797     }
798
799
800
801     private class SubList implements List JavaDoc {
802
803         private int first;
804         private int last;
805         private List JavaDoc expected;
806
807
808         public SubList(int first, int last) {
809             this.first = first;
810             this.last = last;
811             this.expected = list;
812         }
813
814         private List JavaDoc get(List JavaDoc l) {
815             if (list != expected) {
816                 throw new ConcurrentModificationException JavaDoc();
817             }
818             return l.subList(first, last);
819         }
820
821         public void clear() {
822             if (fast) {
823                 synchronized (FastArrayList.this) {
824                     ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
825                     get(temp).clear();
826                     last = first;
827                     list = temp;
828                     expected = temp;
829                 }
830             } else {
831                 synchronized (list) {
832                     get(expected).clear();
833                 }
834             }
835         }
836
837         public boolean remove(Object JavaDoc o) {
838             if (fast) {
839                 synchronized (FastArrayList.this) {
840                     ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
841                     boolean r = get(temp).remove(o);
842                     if (r) last--;
843                     list = temp;
844                     expected = temp;
845                     return r;
846                 }
847             } else {
848                 synchronized (list) {
849                     return get(expected).remove(o);
850                 }
851             }
852         }
853
854         public boolean removeAll(Collection JavaDoc o) {
855             if (fast) {
856                 synchronized (FastArrayList.this) {
857                     ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
858                     List JavaDoc sub = get(temp);
859                     boolean r = sub.removeAll(o);
860                     if (r) last = first + sub.size();
861                     list = temp;
862                     expected = temp;
863                     return r;
864                 }
865             } else {
866                 synchronized (list) {
867                     return get(expected).removeAll(o);
868                 }
869             }
870         }
871
872         public boolean retainAll(Collection JavaDoc o) {
873             if (fast) {
874                 synchronized (FastArrayList.this) {
875                     ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
876                     List JavaDoc sub = get(temp);
877                     boolean r = sub.retainAll(o);
878                     if (r) last = first + sub.size();
879                     list = temp;
880                     expected = temp;
881                     return r;
882                 }
883             } else {
884                 synchronized (list) {
885                     return get(expected).retainAll(o);
886                 }
887             }
888         }
889
890         public int size() {
891             if (fast) {
892                 return get(expected).size();
893             } else {
894                 synchronized (list) {
895                     return get(expected).size();
896                 }
897             }
898         }
899
900
901         public boolean isEmpty() {
902             if (fast) {
903                 return get(expected).isEmpty();
904             } else {
905                 synchronized (list) {
906                     return get(expected).isEmpty();
907                 }
908             }
909         }
910
911         public boolean contains(Object JavaDoc o) {
912             if (fast) {
913                 return get(expected).contains(o);
914             } else {
915                 synchronized (list) {
916                     return get(expected).contains(o);
917                 }
918             }
919         }
920
921         public boolean containsAll(Collection JavaDoc o) {
922             if (fast) {
923                 return get(expected).containsAll(o);
924             } else {
925                 synchronized (list) {
926                     return get(expected).containsAll(o);
927                 }
928             }
929         }
930
931         public Object JavaDoc[] toArray(Object JavaDoc[] o) {
932             if (fast) {
933                 return get(expected).toArray(o);
934             } else {
935                 synchronized (list) {
936                     return get(expected).toArray(o);
937                 }
938             }
939         }
940
941         public Object JavaDoc[] toArray() {
942             if (fast) {
943                 return get(expected).toArray();
944             } else {
945                 synchronized (list) {
946                     return get(expected).toArray();
947                 }
948             }
949         }
950
951
952         public boolean equals(Object JavaDoc o) {
953             if (o == this) return true;
954             if (fast) {
955                 return get(expected).equals(o);
956             } else {
957                 synchronized (list) {
958                     return get(expected).equals(o);
959                 }
960             }
961         }
962
963         public int hashCode() {
964             if (fast) {
965                 return get(expected).hashCode();
966             } else {
967                 synchronized (list) {
968                     return get(expected).hashCode();
969                 }
970             }
971         }
972
973         public boolean add(Object JavaDoc o) {
974             if (fast) {
975                 synchronized (FastArrayList.this) {
976                     ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
977                     boolean r = get(temp).add(o);
978                     if (r) last++;
979                     list = temp;
980                     expected = temp;
981                     return r;
982                 }
983             } else {
984                 synchronized (list) {
985                     return get(expected).add(o);
986                 }
987             }
988         }
989
990         public boolean addAll(Collection JavaDoc o) {
991             if (fast) {
992                 synchronized (FastArrayList.this) {
993                     ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
994                     boolean r = get(temp).addAll(o);
995                     if (r) last += o.size();
996                     list = temp;
997                     expected = temp;
998                     return r;
999                 }
1000            } else {
1001                synchronized (list) {
1002                    return get(expected).addAll(o);
1003                }
1004            }
1005        }
1006
1007        public void add(int i, Object JavaDoc o) {
1008            if (fast) {
1009                synchronized (FastArrayList.this) {
1010                    ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
1011                    get(temp).add(i, o);
1012                    last++;
1013                    list = temp;
1014                    expected = temp;
1015                }
1016            } else {
1017                synchronized (list) {
1018                    get(expected).add(i, o);
1019                }
1020            }
1021        }
1022
1023        public boolean addAll(int i, Collection JavaDoc o) {
1024            if (fast) {
1025                synchronized (FastArrayList.this) {
1026                    ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
1027                    boolean r = get(temp).addAll(i, o);
1028                    list = temp;
1029                    if (r) last += o.size();
1030                    expected = temp;
1031                    return r;
1032                }
1033            } else {
1034                synchronized (list) {
1035                    return get(expected).addAll(i, o);
1036                }
1037            }
1038        }
1039
1040        public Object JavaDoc remove(int i) {
1041            if (fast) {
1042                synchronized (FastArrayList.this) {
1043                    ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
1044                    Object JavaDoc o = get(temp).remove(i);
1045                    last--;
1046                    list = temp;
1047                    expected = temp;
1048                    return o;
1049                }
1050            } else {
1051                synchronized (list) {
1052                    return get(expected).remove(i);
1053                }
1054            }
1055        }
1056
1057        public Object JavaDoc set(int i, Object JavaDoc a) {
1058            if (fast) {
1059                synchronized (FastArrayList.this) {
1060                    ArrayList JavaDoc temp = (ArrayList JavaDoc) list.clone();
1061                    Object JavaDoc o = get(temp).set(i, a);
1062                    list = temp;
1063                    expected = temp;
1064                    return o;
1065                }
1066            } else {
1067                synchronized (list) {
1068                    return get(expected).set(i, a);
1069                }
1070            }
1071        }
1072
1073
1074        public Iterator JavaDoc iterator() {
1075            return new SubListIter(0);
1076        }
1077
1078        public ListIterator JavaDoc listIterator() {
1079            return new SubListIter(0);
1080        }
1081
1082        public ListIterator JavaDoc listIterator(int i) {
1083            return new SubListIter(i);
1084        }
1085
1086
1087        public Object JavaDoc get(int i) {
1088            if (fast) {
1089                return get(expected).get(i);
1090            } else {
1091                synchronized (list) {
1092                    return get(expected).get(i);
1093                }
1094            }
1095        }
1096
1097        public int indexOf(Object JavaDoc o) {
1098            if (fast) {
1099                return get(expected).indexOf(o);
1100            } else {
1101                synchronized (list) {
1102                    return get(expected).indexOf(o);
1103                }
1104            }
1105        }
1106
1107
1108        public int lastIndexOf(Object JavaDoc o) {
1109            if (fast) {
1110                return get(expected).lastIndexOf(o);
1111            } else {
1112                synchronized (list) {
1113                    return get(expected).lastIndexOf(o);
1114                }
1115            }
1116        }
1117
1118
1119        public List JavaDoc subList(int f, int l) {
1120            if (list != expected) {
1121                throw new ConcurrentModificationException JavaDoc();
1122            }
1123            return new SubList(first + f, f + l);
1124        }
1125
1126
1127    private class SubListIter implements ListIterator JavaDoc {
1128
1129        private List JavaDoc expected;
1130        private ListIterator JavaDoc iter;
1131        private int lastReturnedIndex = -1;
1132
1133
1134        public SubListIter(int i) {
1135            this.expected = list;
1136            this.iter = SubList.this.get(expected).listIterator(i);
1137        }
1138
1139        private void checkMod() {
1140            if (list != expected) {
1141                throw new ConcurrentModificationException JavaDoc();
1142            }
1143        }
1144
1145        List JavaDoc get() {
1146            return SubList.this.get(expected);
1147        }
1148
1149        public boolean hasNext() {
1150            checkMod();
1151            return iter.hasNext();
1152        }
1153
1154        public Object JavaDoc next() {
1155            checkMod();
1156            lastReturnedIndex = iter.nextIndex();
1157            return iter.next();
1158        }
1159
1160        public boolean hasPrevious() {
1161            checkMod();
1162            return iter.hasPrevious();
1163        }
1164
1165        public Object JavaDoc previous() {
1166            checkMod();
1167            lastReturnedIndex = iter.previousIndex();
1168            return iter.previous();
1169        }
1170
1171        public int previousIndex() {
1172            checkMod();
1173            return iter.previousIndex();
1174        }
1175
1176        public int nextIndex() {
1177            checkMod();
1178            return iter.nextIndex();
1179        }
1180
1181        public void remove() {
1182            checkMod();
1183            if (lastReturnedIndex < 0) {
1184                throw new IllegalStateException JavaDoc();
1185            }
1186            get().remove(lastReturnedIndex);
1187            last--;
1188            expected = list;
1189            iter = get().listIterator(previousIndex());
1190            lastReturnedIndex = -1;
1191        }
1192
1193        public void set(Object JavaDoc o) {
1194            checkMod();
1195            if (lastReturnedIndex < 0) {
1196                throw new IllegalStateException JavaDoc();
1197            }
1198            get().set(lastReturnedIndex, o);
1199            expected = list;
1200            iter = get().listIterator(previousIndex() + 1);
1201        }
1202
1203        public void add(Object JavaDoc o) {
1204            checkMod();
1205            int i = nextIndex();
1206            get().add(i, o);
1207            last++;
1208            iter = get().listIterator(i + 1);
1209            lastReturnedIndex = 1;
1210        }
1211
1212   }
1213
1214
1215    }
1216
1217
1218
1219    private class ListIter implements ListIterator JavaDoc {
1220
1221        private List JavaDoc expected;
1222        private ListIterator JavaDoc iter;
1223        private int lastReturnedIndex = -1;
1224
1225
1226        public ListIter(int i) {
1227            this.expected = list;
1228            this.iter = get().listIterator(i);
1229        }
1230
1231        private void checkMod() {
1232            if (list != expected) {
1233                throw new ConcurrentModificationException JavaDoc();
1234            }
1235        }
1236
1237        List JavaDoc get() {
1238            return expected;
1239        }
1240
1241        public boolean hasNext() {
1242            checkMod();
1243            return iter.hasNext();
1244        }
1245
1246        public Object JavaDoc next() {
1247            checkMod();
1248            lastReturnedIndex = iter.nextIndex();
1249            return iter.next();
1250        }
1251
1252        public boolean hasPrevious() {
1253            checkMod();
1254            return iter.hasPrevious();
1255        }
1256
1257        public Object JavaDoc previous() {
1258            checkMod();
1259            lastReturnedIndex = iter.previousIndex();
1260            return iter.previous();
1261        }
1262
1263        public int previousIndex() {
1264            checkMod();
1265            return iter.previousIndex();
1266        }
1267
1268        public int nextIndex() {
1269            checkMod();
1270            return iter.nextIndex();
1271        }
1272
1273        public void remove() {
1274            checkMod();
1275            if (lastReturnedIndex < 0) {
1276                throw new IllegalStateException JavaDoc();
1277            }
1278            get().remove(lastReturnedIndex);
1279            expected = list;
1280            iter = get().listIterator(previousIndex());
1281            lastReturnedIndex = -1;
1282        }
1283
1284        public void set(Object JavaDoc o) {
1285            checkMod();
1286            if (lastReturnedIndex < 0) {
1287                throw new IllegalStateException JavaDoc();
1288            }
1289            get().set(lastReturnedIndex, o);
1290            expected = list;
1291            iter = get().listIterator(previousIndex() + 1);
1292        }
1293
1294        public void add(Object JavaDoc o) {
1295            checkMod();
1296            int i = nextIndex();
1297            get().add(i, o);
1298            iter = get().listIterator(i + 1);
1299            lastReturnedIndex = -1;
1300        }
1301
1302   }
1303}
1304
Popular Tags