1 /*
2 * Copyright 2001-2010 Stephen Colebourne
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.joda.primitives.collection.impl;
17
18 import java.util.Collection;
19 import java.util.Iterator;
20 import java.util.NoSuchElementException;
21
22 import org.joda.primitives.DoubleUtils;
23 import org.joda.primitives.collection.DoubleCollection;
24 import org.joda.primitives.iterator.DoubleIterator;
25
26 /**
27 * Array based implementation of <code>DoubleCollection</code> for
28 * primitive <code>double</code> elements.
29 * <p>
30 * This collection implementation allows multiple copies of the same value to be added.
31 * Internally, it uses an array, and behaves much like a list.
32 * <p>
33 * This class implements {@link java.util.Collection Collection} allowing
34 * seamless integration with other APIs.
35 * <p>
36 * Add, Remove and Clear are supported.
37 *
38 * @author Stephen Colebourne
39 * @author Jason Tiscione
40 * @version CODE GENERATED
41 * @since 1.0
42 */
43 public class ArrayDoubleCollection extends AbstractDoubleCollection implements Cloneable {
44 // This file is CODE GENERATED. Do not change manually.
45
46 /** The minimum size allowed when growth occurs */
47 private static final int MIN_GROWTH_SIZE = 4;
48 /** The amount the collection grows by when resized (3/2) */
49 private static final int GROWTH_FACTOR_MULTIPLIER = 3;
50 /** The amount the collection grows by when resized (3/2) */
51 private static final int GROWTH_FACTOR_DIVISOR = 2;
52
53 /** The array of elements */
54 private double[] data;
55 /** The current size */
56 private int size;
57
58 /**
59 * Constructor.
60 */
61 public ArrayDoubleCollection() {
62 super();
63 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
64 }
65
66 /**
67 * Constructor that defines an initial size for the internal storage array.
68 *
69 * @param initialSize the initial size of the internal array, negative treated as zero
70 */
71 public ArrayDoubleCollection(int initialSize) {
72 super();
73 if (initialSize <= 0) {
74 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
75 } else {
76 data = new double[initialSize];
77 }
78 }
79
80 /**
81 * Constructor that copies the specified values.
82 *
83 * @param values an array of values to copy, null treated as zero size array
84 */
85 public ArrayDoubleCollection(double[] values) {
86 super();
87 if (values == null) {
88 data = DoubleUtils.EMPTY_DOUBLE_ARRAY;
89 } else {
90 data = (double[]) values.clone();
91 size = values.length;
92 }
93 }
94
95 /**
96 * Constructs a new collection by copying values from another collection.
97 *
98 * @param coll a collection of values to copy, null treated as zero size collection
99 */
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 }