View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.primitives;
18  
19  import java.util.ConcurrentModificationException;
20  import java.util.NoSuchElementException;
21  
22  /**
23   * Abstract base class for {@link DoubleList}s backed 
24   * by random access structures like arrays.
25   * <p />
26   * Read-only subclasses must override {@link #get}
27   * and {@link #size}.  Mutable subclasses
28   * should also override {@link #set}.  Variably-sized
29   * subclasses should also override {@link #add(double)} 
30   * and {@link #removeElementAt}.  All other methods
31   * have at least some base implementation derived from 
32   * these.  Subclasses may choose to override these methods
33   * to provide a more efficient implementation.
34   * 
35   * @since Commons Primitives 1.0
36   * @version $Revision: 480460 $ $Date: 2006-11-29 03:14:21 -0500 (Wed, 29 Nov 2006) $
37   * 
38   * @author Rodney Waldhoff 
39   */
40  public abstract class RandomAccessDoubleList extends AbstractDoubleCollection implements DoubleList {
41  
42      // constructors
43      //-------------------------------------------------------------------------
44  
45      /** Constructs an empty list. */
46      protected RandomAccessDoubleList() { 
47      }    
48  
49      // fully abstract methods
50      //-------------------------------------------------------------------------
51      
52      public abstract double get(int index);
53      public abstract int size();
54  
55      // unsupported in base
56      //-------------------------------------------------------------------------
57      
58      /** 
59       * Unsupported in this implementation. 
60       * @throws UnsupportedOperationException since this method is not supported
61       */
62      public double removeElementAt(int index) {
63          throw new UnsupportedOperationException();
64      }
65      
66      /** 
67       * Unsupported in this implementation. 
68       * @throws UnsupportedOperationException since this method is not supported
69       */
70      public double set(int index, double element) {
71          throw new UnsupportedOperationException();
72      }
73          
74      /** 
75       * Unsupported in this implementation. 
76       * @throws UnsupportedOperationException since this method is not supported
77       */
78      public void add(int index, double element) {
79          throw new UnsupportedOperationException();
80      }
81  
82      //-------------------------------------------------------------------------
83  
84      // javadocs here are inherited
85      
86      public boolean add(double element) {
87          add(size(),element);
88          return true;
89      }
90  
91      public boolean addAll(int index, DoubleCollection collection) {
92          boolean modified = false;
93          for(DoubleIterator iter = collection.iterator(); iter.hasNext(); ) {
94              add(index++,iter.next());
95              modified = true;
96          }
97          return modified;
98      }
99  
100     public int indexOf(double element) {
101         int i = 0;
102         for(DoubleIterator iter = iterator(); iter.hasNext(); ) {
103             if(iter.next() == element) { 
104                 return i;
105             } else {
106                 i++;
107             }
108         }
109         return -1;
110     }
111 
112     public int lastIndexOf(double element) {
113         for(DoubleListIterator iter = listIterator(size()); iter.hasPrevious(); ) {
114             if(iter.previous() == element) {
115                 return iter.nextIndex();
116             }
117         }
118         return -1;
119     }
120 
121     public DoubleIterator iterator() {
122         return listIterator();
123     }
124 
125     public DoubleListIterator listIterator() {
126         return listIterator(0);
127     }
128 
129     public DoubleListIterator listIterator(int index) {
130         return new RandomAccessDoubleListIterator(this,index);            
131     }
132 
133     public DoubleList subList(int fromIndex, int toIndex) {
134         return new RandomAccessDoubleSubList(this,fromIndex,toIndex);
135     }
136 
137     public boolean equals(Object that) {
138         if(this == that) { 
139             return true; 
140         } else if(that instanceof DoubleList) {
141             DoubleList thatList = (DoubleList)that;
142             if(size() != thatList.size()) {
143                 return false;
144             }
145             for(DoubleIterator thatIter = thatList.iterator(), thisIter = iterator(); thisIter.hasNext();) {
146                 if(thisIter.next() != thatIter.next()) { 
147                     return false; 
148                 }
149             }
150             return true;
151         } else {
152             return false;
153         }        
154     }
155     
156     public int hashCode() {
157         int hash = 1;
158         for(DoubleIterator iter = iterator(); iter.hasNext(); ) {
159             long bits = Double.doubleToLongBits(iter.next());
160             hash = 31*hash + ((int)(bits ^ (bits >>> 32)));
161         }
162         return hash;
163     }
164     
165     public String toString() {
166         StringBuffer buf = new StringBuffer();
167         buf.append("[");
168         for(DoubleIterator iter = iterator(); iter.hasNext();) {
169             buf.append(iter.next());
170             if(iter.hasNext()) {
171                 buf.append(", ");
172             }
173         }
174         buf.append("]");
175         return buf.toString();
176     }
177     
178     // protected utilities
179     //-------------------------------------------------------------------------
180     
181     /** Get my count of structural modifications. */
182     protected int getModCount() {
183         return _modCount;
184     }
185 
186     /** Increment my count of structural modifications. */
187     protected void incrModCount() {
188         _modCount++;
189     }
190 
191     // attributes
192     //-------------------------------------------------------------------------
193     
194     private int _modCount = 0;
195 
196     // inner classes
197     //-------------------------------------------------------------------------
198     
199     private static class ComodChecker {
200         ComodChecker(RandomAccessDoubleList source) {
201             _source = source;  
202             resyncModCount();             
203         }
204         
205         protected RandomAccessDoubleList getList() {
206             return _source;
207         }
208         
209         protected void assertNotComodified() throws ConcurrentModificationException {
210             if(_expectedModCount != getList().getModCount()) {
211                 throw new ConcurrentModificationException();
212             }
213         }
214             
215         protected void resyncModCount() {
216             _expectedModCount = getList().getModCount();
217         }
218         
219         private RandomAccessDoubleList _source = null;
220         private int _expectedModCount = -1;
221     }
222     
223     protected static class RandomAccessDoubleListIterator extends ComodChecker implements DoubleListIterator {
224         RandomAccessDoubleListIterator(RandomAccessDoubleList list, int index) {
225             super(list);
226             if(index < 0 || index > getList().size()) {
227                 throw new IndexOutOfBoundsException("Index " + index + " not in [0," + getList().size() + ")");
228             } else {
229                 _nextIndex = index;
230                 resyncModCount();
231             }
232         }
233             
234         public boolean hasNext() {
235             assertNotComodified();
236             return _nextIndex < getList().size();
237         }
238         
239         public boolean hasPrevious() {
240             assertNotComodified();
241             return _nextIndex > 0;
242         }
243         
244         public int nextIndex() {
245             assertNotComodified();
246             return _nextIndex;
247         }
248         
249         public int previousIndex() {
250             assertNotComodified();
251             return _nextIndex - 1;
252         }
253         
254         public double next() {
255             assertNotComodified();
256             if(!hasNext()) {
257                 throw new NoSuchElementException();
258             } else {
259                 double val = getList().get(_nextIndex);
260                 _lastReturnedIndex = _nextIndex;
261                 _nextIndex++;
262                 return val;
263             }
264         }
265         
266         public double previous() {
267             assertNotComodified();
268             if(!hasPrevious()) {
269                 throw new NoSuchElementException();
270             } else {
271                 double val = getList().get(_nextIndex-1);
272                 _lastReturnedIndex = _nextIndex-1;
273                 _nextIndex--;
274                 return val;
275             }
276         }
277         
278         public void add(double value) {
279             assertNotComodified();
280             getList().add(_nextIndex,value);
281             _nextIndex++;
282             _lastReturnedIndex = -1;
283             resyncModCount();
284         }
285     
286         public void remove() {
287             assertNotComodified();
288             if (_lastReturnedIndex == -1) {
289                 throw new IllegalStateException();
290             }
291             if (_lastReturnedIndex == _nextIndex) {
292                 // remove() following previous()
293                 getList().removeElementAt(_lastReturnedIndex);
294             } else {
295                 // remove() following next()
296                 getList().removeElementAt(_lastReturnedIndex);
297                 _nextIndex--;
298             }
299             _lastReturnedIndex = -1;
300             resyncModCount();
301         }
302         
303         public void set(double value) {
304             assertNotComodified();
305             if(-1 == _lastReturnedIndex) {
306                 throw new IllegalStateException();
307             } else {
308                 getList().set(_lastReturnedIndex,value);
309                 resyncModCount();
310             }
311         }
312         
313         private int _nextIndex = 0;
314         private int _lastReturnedIndex = -1;        
315     }   
316 
317     protected static class RandomAccessDoubleSubList extends RandomAccessDoubleList implements DoubleList {
318         RandomAccessDoubleSubList(RandomAccessDoubleList list, int fromIndex, int toIndex) {
319             if(fromIndex < 0 || toIndex > list.size()) {
320                 throw new IndexOutOfBoundsException();
321             } else if(fromIndex > toIndex) {
322                 throw new IllegalArgumentException();                
323             } else {
324                 _list = list;
325                 _offset = fromIndex;
326                 _limit = toIndex - fromIndex;
327                 _comod = new ComodChecker(list);
328                 _comod.resyncModCount();
329             }            
330         }
331     
332         public double get(int index) {
333             checkRange(index);
334             _comod.assertNotComodified();
335             return _list.get(toUnderlyingIndex(index));
336         }
337     
338         public double removeElementAt(int index) {
339             checkRange(index);
340             _comod.assertNotComodified();
341             double val = _list.removeElementAt(toUnderlyingIndex(index));
342             _limit--;
343             _comod.resyncModCount();
344             incrModCount();
345             return val;
346         }
347     
348         public double set(int index, double element) {
349             checkRange(index);
350             _comod.assertNotComodified();
351             double val = _list.set(toUnderlyingIndex(index),element);
352             incrModCount();
353             _comod.resyncModCount();
354             return val;
355         }
356     
357         public void add(int index, double element) {
358             checkRangeIncludingEndpoint(index);
359             _comod.assertNotComodified();
360              _list.add(toUnderlyingIndex(index),element);
361             _limit++;
362             _comod.resyncModCount();
363             incrModCount();
364         }
365     
366         public int size() {
367             _comod.assertNotComodified();
368             return _limit;
369         }
370     
371         private void checkRange(int index) {
372             if(index < 0 || index >= size()) {
373                 throw new IndexOutOfBoundsException("index " + index + " not in [0," + size() + ")");
374             }
375         }
376           
377         private void checkRangeIncludingEndpoint(int index) {
378             if(index < 0 || index > size()) {
379                 throw new IndexOutOfBoundsException("index " + index + " not in [0," + size() + "]");
380             }
381         }
382           
383         private int toUnderlyingIndex(int index) {
384             return (index + _offset);
385         }
386         
387         private int _offset = 0;        
388         private int _limit = 0; 
389         private RandomAccessDoubleList _list = null;
390         private ComodChecker _comod = null;
391     
392     }
393 }
394