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.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.io.Serializable;
23  
24  /**
25   * An {@link IntList} backed by an array of unsigned
26   * <code>short</code> values.
27   * This list stores <code>int</code> values
28   * in the range [{@link #MIN_VALUE <code>0</code>},
29   * {@link #MAX_VALUE <code>65535</code>}] in 16-bits 
30   * per element.  Attempts to use elements outside this 
31   * range may cause an 
32   * {@link IllegalArgumentException IllegalArgumentException} 
33   * to be thrown.
34   * <p />
35   * This implementation supports all optional methods.
36   * 
37   * @since Commons Primitives 1.0
38   * @version $Revision: 480460 $ $Date: 2006-11-29 03:14:21 -0500 (Wed, 29 Nov 2006) $
39   * 
40   * @author Rodney Waldhoff 
41   */
42  public class ArrayUnsignedShortList extends RandomAccessIntList implements IntList, Serializable {
43  
44      // constructors
45      //-------------------------------------------------------------------------
46  
47      /** 
48       * Construct an empty list with the default
49       * initial capacity.
50       */
51      public ArrayUnsignedShortList() {
52          this(8);
53      }    
54  
55      /**
56       * Construct an empty list with the given
57       * initial capacity.
58       * @throws IllegalArgumentException when <i>initialCapacity</i> is negative
59       */
60      public ArrayUnsignedShortList(int initialCapacity) {
61          if(initialCapacity < 0) {
62              throw new IllegalArgumentException("capacity " + initialCapacity);
63          }
64          _data = new short[initialCapacity];
65          _size = 0;
66      }    
67  
68      /** 
69       * Constructs a list containing the elements of the given collection, 
70       * in the order they are returned by that collection's iterator.
71       * 
72       * @see ArrayIntList#addAll(org.apache.commons.collections.primitives.IntCollection)
73       * @param that the non-<code>null</code> collection of <code>int</code>s 
74       *        to add
75       * @throws NullPointerException if <i>that</i> is <code>null</code>
76       */
77      public ArrayUnsignedShortList(IntCollection that) { 
78          this(that.size());
79          addAll(that);
80      }    
81  
82      /**
83       * Constructs a list by copying the specified array.
84       * 
85       * @param array  the array to initialize the collection with
86       * @throws NullPointerException if the array is <code>null</code>
87       */
88      public ArrayUnsignedShortList(int[] array) { 
89          this(array.length);
90          for(int i=0;i<array.length;i++) {
91              _data[i] = fromInt(array[i]);
92          }
93          _size = array.length;
94      }
95      
96      // IntList methods
97      //-------------------------------------------------------------------------
98  
99      /** 
100      * Returns the element at the specified position within 
101      * me. 
102      * By construction, the returned value will be 
103      * between {@link #MIN_VALUE} and {@link #MAX_VALUE}, inclusive.
104      * 
105      * @param index the index of the element to return
106      * @return the value of the element at the specified position
107      * @throws IndexOutOfBoundsException if the specified index is out of range
108      */
109     public int get(int index) {
110         checkRange(index);
111         return toInt(_data[index]);
112     }
113     
114     public int size() {
115         return _size;
116     }
117     
118     /** 
119      * Removes the element at the specified position in 
120      * (optional operation).  Any subsequent elements 
121      * are shifted to the left, subtracting one from their 
122      * indices.  Returns the element that was removed.
123      * By construction, the returned value will be 
124      * between {@link #MIN_VALUE} and {@link #MAX_VALUE}, inclusive.
125      * 
126      * @param index the index of the element to remove
127      * @return the value of the element that was removed
128      * 
129      * @throws UnsupportedOperationException when this operation is not 
130      *         supported
131      * @throws IndexOutOfBoundsException if the specified index is out of range
132      */
133     public int removeElementAt(int index) {
134         checkRange(index);
135         incrModCount();
136         int oldval = toInt(_data[index]);
137         int numtomove = _size - index - 1;
138         if(numtomove > 0) {
139             System.arraycopy(_data,index+1,_data,index,numtomove);
140         }
141         _size--;
142         return oldval;
143     }
144     
145     /** 
146      * Replaces the element at the specified 
147      * position in me with the specified element
148      * (optional operation). 
149      * Throws {@link IllegalArgumentException} if <i>element</i>
150      * is less than {@link #MIN_VALUE} or greater than {@link #MAX_VALUE}.
151      * 
152      * @param index the index of the element to change
153      * @param element the value to be stored at the specified position
154      * @return the value previously stored at the specified position
155      * 
156      * @throws UnsupportedOperationException when this operation is not 
157      *         supported
158      * @throws IndexOutOfBoundsException if the specified index is out of range
159      */
160     public int set(int index, int element) {
161         assertValidUnsignedShort(element);
162         checkRange(index);
163         incrModCount();
164         int oldval = toInt(_data[index]);
165         _data[index] = fromInt(element);
166         return oldval;
167     }
168         
169     /** 
170      * Inserts the specified element at the specified position 
171      * (optional operation). Shifts the element currently 
172      * at that position (if any) and any subsequent elements to the 
173      * right, increasing their indices.
174      * Throws {@link IllegalArgumentException} if <i>element</i>
175      * is less than {@link #MIN_VALUE} or greater than {@link #MAX_VALUE}.
176      * 
177      * @param index the index at which to insert the element
178      * @param element the value to insert
179      * 
180      * @throws UnsupportedOperationException when this operation is not 
181      *         supported
182      * @throws IllegalArgumentException if some aspect of the specified element 
183      *         prevents it from being added to me
184      * @throws IndexOutOfBoundsException if the specified index is out of range
185      */
186     public void add(int index, int element) {
187         assertValidUnsignedShort(element);
188         checkRangeIncludingEndpoint(index);
189         incrModCount();
190         ensureCapacity(_size+1);
191         int numtomove = _size-index;
192         System.arraycopy(_data,index,_data,index+1,numtomove);
193         _data[index] = fromInt(element);
194         _size++;
195     }
196 
197     public void clear() {
198         incrModCount();
199         _size = 0;
200     }
201 
202     // capacity methods
203     //-------------------------------------------------------------------------
204 
205     /** 
206      * Increases my capacity, if necessary, to ensure that I can hold at 
207      * least the number of elements specified by the minimum capacity 
208      * argument without growing.
209      */
210     public void ensureCapacity(int mincap) {
211         incrModCount();
212         if(mincap > _data.length) {
213             int newcap = (_data.length * 3)/2 + 1;
214             short[] olddata = _data;
215             _data = new short[newcap < mincap ? mincap : newcap];
216             System.arraycopy(olddata,0,_data,0,_size);
217         }
218     }
219 
220     /** 
221      * Reduce my capacity, if necessary, to match my
222      * current {@link #size size}.
223      */
224     public void trimToSize() {
225         incrModCount();
226         if(_size < _data.length) {
227             short[] olddata = _data;
228             _data = new short[_size];
229             System.arraycopy(olddata,0,_data,0,_size);
230         }
231     }
232 
233     // private methods
234     //-------------------------------------------------------------------------
235 
236     private final int toInt(short value) { 
237         return value & MAX_VALUE;
238     }
239 
240     private final short fromInt(int value) {
241         return (short)(value&MAX_VALUE);
242     }
243 
244     private final void assertValidUnsignedShort(int value) throws IllegalArgumentException {
245         if(value > MAX_VALUE) {
246             throw new IllegalArgumentException(value + " > " + MAX_VALUE);
247         }
248         if(value < MIN_VALUE) {
249             throw new IllegalArgumentException(value + " < " + MIN_VALUE);
250         }
251     }
252 
253     private void writeObject(ObjectOutputStream out) throws IOException{
254         out.defaultWriteObject();
255         out.writeInt(_data.length);
256         for(int i=0;i<_size;i++) {
257             out.writeShort(_data[i]);
258         }
259     }
260 
261     private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
262         in.defaultReadObject();
263         _data = new short[in.readInt()];
264         for(int i=0;i<_size;i++) {
265             _data[i] = in.readShort();
266         }
267     }
268     
269     private final void checkRange(int index) {
270         if(index < 0 || index >= _size) {
271             throw new IndexOutOfBoundsException("Should be at least 0 and less than " + _size + ", found " + index);
272         }
273     }
274 
275     private final void checkRangeIncludingEndpoint(int index) {
276         if(index < 0 || index > _size) {
277             throw new IndexOutOfBoundsException("Should be at least 0 and at most " + _size + ", found " + index);
278         }
279     }
280 
281     // attributes
282     //-------------------------------------------------------------------------
283     
284     /** The maximum possible unsigned 16-bit value (<code>0xFFFF</code>). */
285     public static final int MAX_VALUE = 0xFFFF;
286 
287 
288     /** The minimum possible unsigned 16-bit value  (<code>0x0000</code>). */
289     public static final int MIN_VALUE = 0;
290 
291     private transient short[] _data = null;
292     private int _size = 0;
293 
294 }