001 /*
002 * Copyright 2001-2010 Stephen Colebourne
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.joda.primitives.collection.impl;
017
018 import java.util.Collection;
019 import java.util.Iterator;
020 import java.util.NoSuchElementException;
021
022 import org.joda.primitives.DoubleUtils;
023 import org.joda.primitives.collection.DoubleCollection;
024 import org.joda.primitives.iterator.DoubleIterator;
025
026 /**
027 * Array based implementation of <code>DoubleCollection</code> for
028 * primitive <code>double</code> elements.
029 * <p>
030 * This collection implementation allows multiple copies of the same value to be added.
031 * Internally, it uses an array, and behaves much like a list.
032 * <p>
033 * This class implements {@link java.util.Collection Collection} allowing
034 * seamless integration with other APIs.
035 * <p>
036 * Add, Remove and Clear are supported.
037 *
038 * @author Stephen Colebourne
039 * @author Jason Tiscione
040 * @version CODE GENERATED
041 * @since 1.0
042 */
043 public class ArrayDoubleCollection extends AbstractDoubleCollection implements Cloneable {
044 // This file is CODE GENERATED. Do not change manually.
045
046 /** The minimum size allowed when growth occurs */
047 private static final int MIN_GROWTH_SIZE = 4;
048 /** The amount the collection grows by when resized (3/2) */
049 private static final int GROWTH_FACTOR_MULTIPLIER = 3;
050 /** The amount the collection grows by when resized (3/2) */
051 private static final int GROWTH_FACTOR_DIVISOR = 2;
052
053 /** The array of elements */
054 private double[] data;
055 /** The current size */
056 private int size;
057
058 /**
059 * Constructor.
060 */
061 public ArrayDoubleCollection() {
062 super();
063 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
064 }
065
066 /**
067 * Constructor that defines an initial size for the internal storage array.
068 *
069 * @param initialSize the initial size of the internal array, negative treated as zero
070 */
071 public ArrayDoubleCollection(int initialSize) {
072 super();
073 if (initialSize <= 0) {
074 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
075 } else {
076 data = new double[initialSize];
077 }
078 }
079
080 /**
081 * Constructor that copies the specified values.
082 *
083 * @param values an array of values to copy, null treated as zero size array
084 */
085 public ArrayDoubleCollection(double[] values) {
086 super();
087 if (values == null) {
088 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
089 } else {
090 data = (double[]) values.clone();
091 size = values.length;
092 }
093 }
094
095 /**
096 * Constructs a new collection by copying values from another collection.
097 *
098 * @param coll a collection of values to copy, null treated as zero size collection
099 */
100 public ArrayDoubleCollection(Collection<?> coll) {
101 super();
102 if (coll == null) {
103 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
104 } else if (coll instanceof DoubleCollection) {
105 DoubleCollection c = (DoubleCollection) coll;
106 size = c.size();
107 data = new double[size];
108 c.toDoubleArray(data, 0);
109 } else {
110 data = toPrimitiveArray(coll);
111 size = coll.size();
112 }
113 }
114
115 /**
116 * Constructs a new collection by copying values from an iterator.
117 *
118 * @param it an iterator of values to extract, null treated as zero size collection
119 */
120 public ArrayDoubleCollection(Iterator<Double> it) {
121 super();
122 if (it == null) {
123 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
124 } else if (it instanceof DoubleIterator) {
125 DoubleIterator typed = (DoubleIterator) it;
126 data = new double[MIN_GROWTH_SIZE];
127 while (typed.hasNext()) {
128 add(typed.nextDouble());
129 }
130 } else {
131 data = new double[MIN_GROWTH_SIZE];
132 while (it.hasNext()) {
133 add(it.next());
134 }
135 }
136 }
137
138 // Implementation
139 //-----------------------------------------------------------------------
140 /**
141 * Gets the current size of the collection.
142 *
143 * @return the current size
144 */
145 public int size() {
146 return size;
147 }
148
149 /**
150 * Gets an iterator over this collection capable of accessing the primitive values.
151 *
152 * @return an iterator over this collection
153 */
154 public DoubleIterator iterator() {
155 return new PIterator(this);
156 }
157
158 /**
159 * Adds a primitive value to this collection.
160 *
161 * @param value the value to add to this collection
162 * @return <code>true</code> if this collection was modified by this method call
163 * @throws IllegalArgumentException if value is rejected by this collection
164 */
165 public boolean add(double value) {
166 ensureCapacity(size + 1);
167 data[size++] = value;
168 return true;
169 }
170
171 // Overrides
172 //-----------------------------------------------------------------------
173 /**
174 * Optimizes the implementation.
175 * <p>
176 * This implementation changes the internal array to be the same size as
177 * the size of the collection.
178 */
179 public void optimize() {
180 if (size < data.length) {
181 double[] array = new double[size];
182 System.arraycopy(data, 0, array, 0, size);
183 data = array;
184 }
185 }
186
187 /**
188 * Are the add methods supported.
189 *
190 * @return <code>true</code>
191 */
192 protected boolean isAddModifiable() {
193 return true;
194 }
195
196 /**
197 * Are the remove methods supported.
198 *
199 * @return <code>true</code>
200 */
201 protected boolean isRemoveModifiable() {
202 return true;
203 }
204
205 /**
206 * Checks whether the object can currently be modified.
207 *
208 * @return <code>true</code>
209 */
210 public boolean isModifiable() {
211 return true;
212 }
213
214 /**
215 * Checks whether this collection contains a specified primitive value.
216 * <p>
217 * This implementation uses the internal array directly.
218 *
219 * @param value the value to search for
220 * @return <code>true</code> if the value is found
221 */
222 public boolean contains(double value) {
223 for (int i = 0; i < size; i++) {
224 if (data[i] == value) {
225 return true;
226 }
227 }
228 return false;
229 }
230
231 /**
232 * Clears the collection of all elements.
233 * The collection will have a zero size after this method completes.
234 * <p>
235 * This implementation resets the size, but does not reduce the internal storage array.
236 */
237 public void clear() {
238 size = 0;
239 }
240
241 /**
242 * Adds an array of primitive values to this collection.
243 *
244 * @param values the values to add to this collection
245 * @return <code>true</code> if this collection was modified by this method call
246 */
247 public boolean addAll(double[] values) {
248 checkAddModifiable();
249 if (values == null || values.length == 0) {
250 return false;
251 }
252 return doAdd(0, values);
253 }
254
255 /**
256 * Adds a collection of primitive values to this collection.
257 *
258 * @param values the values to add to this collection, null treated as empty collection
259 * @return <code>true</code> if this collection was modified by this method call
260 */
261 public boolean addAll(DoubleCollection values) {
262 checkAddModifiable();
263 if (values == null || values.size() == 0) {
264 return false;
265 }
266 int len = values.size();
267 ensureCapacity(size + len);
268 values.toDoubleArray(data, size);
269 size += len;
270 return true;
271 }
272
273 /**
274 * Clone implementation that calls Object clone().
275 *
276 * @return the clone
277 */
278 public Object clone() {
279 ArrayDoubleCollection cloned = (ArrayDoubleCollection) super.clone();
280 cloned.data = (double[]) data.clone();
281 return cloned;
282 }
283
284 /**
285 * Copies data from this collection into the specified array.
286 * This method is pre-validated.
287 *
288 * @param fromIndex the index to start from
289 * @param dest the destination array
290 * @param destIndex the destination start index
291 * @param size the number of items to copy
292 */
293 protected void arrayCopy(int fromIndex, double[] dest, int destIndex, int size) {
294 System.arraycopy(data, fromIndex, dest, destIndex, size);
295 }
296
297 // Internal implementation
298 //-----------------------------------------------------------------------
299 /**
300 * Internal implementation to add to this collection at the specified index.
301 * This method adjusts the capacity and size.
302 *
303 * @param index the index to add at, valid
304 * @param values the array to add, not null
305 * @return true if the array was updated
306 */
307 protected boolean doAdd(int index, double[] values) {
308 int len = values.length;
309 ensureCapacity(size + len);
310 System.arraycopy(values, 0, data, size, len);
311 size += len;
312 return (len > 0);
313 }
314
315 /**
316 * Internal implementation to remove the element at the specified index.
317 *
318 * @param index the index, valid
319 */
320 protected void doRemoveIndex(int index) {
321 System.arraycopy(data, index + 1, data, index, size - 1 - index);
322 size--;
323 }
324
325 /**
326 * Internal implementation to ensure that the internal storage array has
327 * at least the specified size.
328 *
329 * @param reqCapacity the amount to expand to
330 */
331 protected void ensureCapacity(int reqCapacity) {
332 int curCapacity = data.length;
333 if (reqCapacity <= curCapacity) {
334 return;
335 }
336 int newCapacity = curCapacity * GROWTH_FACTOR_MULTIPLIER / GROWTH_FACTOR_DIVISOR;
337 if ((newCapacity - curCapacity) < MIN_GROWTH_SIZE) {
338 newCapacity = curCapacity + MIN_GROWTH_SIZE;
339 }
340 if (newCapacity < reqCapacity) {
341 newCapacity = reqCapacity;
342 }
343 double[] newArray = new double[newCapacity];
344 System.arraycopy(data, 0, newArray, 0, curCapacity);
345 data = newArray;
346 }
347
348 // Iterator
349 //-----------------------------------------------------------------------
350 /**
351 * Iterator.
352 */
353 protected static class PIterator implements DoubleIterator {
354
355 private final ArrayDoubleCollection collection;
356 private int cursor = 0;
357 private boolean canRemove = false;
358
359 protected PIterator(ArrayDoubleCollection coll) {
360 super();
361 this.collection = coll;
362 }
363
364 public boolean hasNext() {
365 return (cursor < collection.size);
366 }
367
368 public double nextDouble() {
369 if (hasNext() == false) {
370 throw new NoSuchElementException("No more elements available");
371 }
372 canRemove = true;
373 return collection.data[cursor++];
374 }
375
376 public Double next() {
377 return collection.toObject(nextDouble());
378 }
379
380 public void remove() {
381 if (canRemove == false) {
382 throw new IllegalStateException("Element cannot be removed");
383 }
384 collection.doRemoveIndex(--cursor);
385 canRemove = false;
386 }
387
388 public boolean isModifiable() {
389 return collection.isModifiable();
390 }
391
392 public boolean isResettable() {
393 return true;
394 }
395
396 public void reset() {
397 cursor = 0;
398 }
399 }
400
401 }