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.LongUtils;
023 import org.joda.primitives.collection.LongCollection;
024 import org.joda.primitives.iterator.LongIterator;
025
026 /**
027 * Array based implementation of <code>LongCollection</code> for
028 * primitive <code>long</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 ArrayLongCollection extends AbstractLongCollection 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 long[] data;
055 /** The current size */
056 private int size;
057
058 /**
059 * Constructor.
060 */
061 public ArrayLongCollection() {
062 super();
063 data = LongUtils.EMPTY_LONG_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 ArrayLongCollection(int initialSize) {
072 super();
073 if (initialSize <= 0) {
074 data = LongUtils.EMPTY_LONG_ARRAY;
075 } else {
076 data = new long[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 ArrayLongCollection(long[] values) {
086 super();
087 if (values == null) {
088 data = LongUtils.EMPTY_LONG_ARRAY;
089 } else {
090 data = (long[]) 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 ArrayLongCollection(Collection<?> coll) {
101 super();
102 if (coll == null) {
103 data = LongUtils.EMPTY_LONG_ARRAY;
104 } else if (coll instanceof LongCollection) {
105 LongCollection c = (LongCollection) coll;
106 size = c.size();
107 data = new long[size];
108 c.toLongArray(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 ArrayLongCollection(Iterator<Long> it) {
121 super();
122 if (it == null) {
123 data = LongUtils.EMPTY_LONG_ARRAY;
124 } else if (it instanceof LongIterator) {
125 LongIterator typed = (LongIterator) it;
126 data = new long[MIN_GROWTH_SIZE];
127 while (typed.hasNext()) {
128 add(typed.nextLong());
129 }
130 } else {
131 data = new long[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 LongIterator 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(long 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 long[] array = new long[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(long 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(long[] 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(LongCollection 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.toLongArray(data, size);
269 size += len;
270 return true;
271 }
272
273 /**
274 * Adds a range of primitive values to this collection.
275 * <p>
276 * The range is defined to be inclusive of the start and end.
277 * If the start is greater than the end then the range is equivalent to an empty collection.
278 *
279 * @param startInclusive the inclusive range start value
280 * @param endInclusive the inclusive range end value
281 * @return <code>true</code> if this collection was modified by this method call
282 * @throws IllegalArgumentException if a value is rejected by this set
283 * @throws UnsupportedOperationException if not supported by this set
284 */
285 public boolean addAll(long startInclusive, long endInclusive) {
286 long increaseLong = endInclusive - startInclusive + 1;
287 if (increaseLong < 0L) {
288 return false;
289 }
290 long newSize = size + increaseLong;
291 if (newSize > Integer.MAX_VALUE) {
292 throw new IllegalArgumentException("Range too large");
293 }
294 ensureCapacity((int) newSize);
295 long i = startInclusive;
296 while (i < endInclusive) {
297 data[size++] = i++;
298 }
299 data[size++] = i; // handles endInclusive=MAX_VALUE
300 return true;
301 }
302
303 /**
304 * Clone implementation that calls Object clone().
305 *
306 * @return the clone
307 */
308 public Object clone() {
309 ArrayLongCollection cloned = (ArrayLongCollection) super.clone();
310 cloned.data = (long[]) data.clone();
311 return cloned;
312 }
313
314 /**
315 * Copies data from this collection into the specified array.
316 * This method is pre-validated.
317 *
318 * @param fromIndex the index to start from
319 * @param dest the destination array
320 * @param destIndex the destination start index
321 * @param size the number of items to copy
322 */
323 protected void arrayCopy(int fromIndex, long[] dest, int destIndex, int size) {
324 System.arraycopy(data, fromIndex, dest, destIndex, size);
325 }
326
327 // Internal implementation
328 //-----------------------------------------------------------------------
329 /**
330 * Internal implementation to add to this collection at the specified index.
331 * This method adjusts the capacity and size.
332 *
333 * @param index the index to add at, valid
334 * @param values the array to add, not null
335 * @return true if the array was updated
336 */
337 protected boolean doAdd(int index, long[] values) {
338 int len = values.length;
339 ensureCapacity(size + len);
340 System.arraycopy(values, 0, data, size, len);
341 size += len;
342 return (len > 0);
343 }
344
345 /**
346 * Internal implementation to remove the element at the specified index.
347 *
348 * @param index the index, valid
349 */
350 protected void doRemoveIndex(int index) {
351 System.arraycopy(data, index + 1, data, index, size - 1 - index);
352 size--;
353 }
354
355 /**
356 * Internal implementation to ensure that the internal storage array has
357 * at least the specified size.
358 *
359 * @param reqCapacity the amount to expand to
360 */
361 protected void ensureCapacity(int reqCapacity) {
362 int curCapacity = data.length;
363 if (reqCapacity <= curCapacity) {
364 return;
365 }
366 int newCapacity = curCapacity * GROWTH_FACTOR_MULTIPLIER / GROWTH_FACTOR_DIVISOR;
367 if ((newCapacity - curCapacity) < MIN_GROWTH_SIZE) {
368 newCapacity = curCapacity + MIN_GROWTH_SIZE;
369 }
370 if (newCapacity < reqCapacity) {
371 newCapacity = reqCapacity;
372 }
373 long[] newArray = new long[newCapacity];
374 System.arraycopy(data, 0, newArray, 0, curCapacity);
375 data = newArray;
376 }
377
378 // Iterator
379 //-----------------------------------------------------------------------
380 /**
381 * Iterator.
382 */
383 protected static class PIterator implements LongIterator {
384
385 private final ArrayLongCollection collection;
386 private int cursor = 0;
387 private boolean canRemove = false;
388
389 protected PIterator(ArrayLongCollection coll) {
390 super();
391 this.collection = coll;
392 }
393
394 public boolean hasNext() {
395 return (cursor < collection.size);
396 }
397
398 public long nextLong() {
399 if (hasNext() == false) {
400 throw new NoSuchElementException("No more elements available");
401 }
402 canRemove = true;
403 return collection.data[cursor++];
404 }
405
406 public Long next() {
407 return collection.toObject(nextLong());
408 }
409
410 public void remove() {
411 if (canRemove == false) {
412 throw new IllegalStateException("Element cannot be removed");
413 }
414 collection.doRemoveIndex(--cursor);
415 canRemove = false;
416 }
417
418 public boolean isModifiable() {
419 return collection.isModifiable();
420 }
421
422 public boolean isResettable() {
423 return true;
424 }
425
426 public void reset() {
427 cursor = 0;
428 }
429 }
430
431 }