001 /*
002 * Java Genetic Algorithm Library (jenetics-3.5.0).
003 * Copyright (c) 2007-2016 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
019 */
020 package org.jenetics.internal.collection;
021
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024
025 import java.io.Serializable;
026 import java.util.Collection;
027 import java.util.Iterator;
028
029 /**
030 * Array implementation class. This class manages the actual array (store) and
031 * the start index and the length.
032 *
033 * @param <T> the array element type
034 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
035 * @version 3.4
036 * @since 3.4
037 */
038 public final class Array<T> implements Serializable {
039 private static final long serialVersionUID = 1L;
040
041 private final Store.Ref<T> _store;
042 private final int _start;
043 private final int _length;
044
045 /**
046 * Private <i>primary</i> constructor.
047 *
048 * @param store the store used by this array
049 * @param from the start index of the array
050 * @param until the end index of the array
051 */
052 private Array(final Store.Ref<T> store, final int from, final int until) {
053 _store = requireNonNull(store);
054 _start = from;
055 _length = until - from;
056 }
057
058 /**
059 * Create a new array from the given store
060 *
061 * @param store the store used by this array
062 */
063 private Array(final Store<T> store) {
064 this(Store.Ref.of(store), 0, store.length());
065 }
066
067 /**
068 * Return the underlying array store.
069 *
070 * @return the underlying array store
071 */
072 public Store<T> store() {
073 return _store._value;
074 }
075
076 public void copyIfSealed() {
077 _store.copyIfSealed();
078 }
079
080 /**
081 * Return a new <i>sealed</i> array instance. The underlying store is sealed
082 * as well, but not copied.
083 *
084 * @return a new sealed array
085 */
086 public final Array<T> seal() {
087 return new Array<>(_store.seal(), _start, _length + _start);
088 }
089
090 /**
091 * Return the seal state of the array.
092 *
093 * @return {@code true} is the array is sealed, {@code false} otherwise
094 */
095 public boolean isSealed() {
096 return _store.isSealed();
097 }
098
099 /**
100 * Set the {@code value} at the given {@code index}. The array index is not
101 * checked.
102 *
103 * @param index the array index
104 * @param value the value to set
105 */
106 public void set(final int index, final T value) {
107 _store.set(index + _start, value);
108 }
109
110 /**
111 * Get the array value at the given {@code index}. The array index is not
112 * checked.
113 *
114 * @param index the array index
115 * @return the value at the given index
116 */
117 public T get(final int index) {
118 return _store.get(index + _start);
119 }
120
121 /**
122 * Return a <i>new</i> {@code Array} object with the given values appended.
123 *
124 * @since 3.4
125 *
126 * @param array the values to append
127 * @return a <i>new</i> {@code Array} object with the elements of
128 * {@code this} array and the given {@code array} appended.
129 * @throws NullPointerException if the given {@code array} is {@code null}
130 */
131 public Array<T> append(final Array<T> array) {
132 final Array<T> appended = newInstance(length() + array.length());
133 for (int i = 0; i < _length; ++i) {
134 appended.set(i, get(i));
135 }
136 for (int i = 0; i < array._length; ++i) {
137 appended.set(i + _length, array.get(i));
138 }
139
140 return appended;
141 }
142
143 private Array<T> newInstance(final int length) {
144 return of(_store._value.newInstance(length));
145 }
146
147 /**
148 * Return a <i>new</i> {@code Array} with the given {@code values} appended.
149 *
150 * @since 3.4
151 *
152 * @param values the values to append
153 * @return a <i>new</i> {@code Array} with the elements of {@code this}
154 * array and the given {@code values} appended.
155 * @throws NullPointerException if the given {@code values} iterable is
156 * {@code null}
157 */
158 public Array<T> append(final Iterable<? extends T> values) {
159 final int size = size(values);
160 final Array<T> array = newInstance(_length + size);
161
162 for (int i = 0; i < _length; ++i) {
163 array.set(i, get(i));
164 }
165
166 final Iterator<? extends T> it = values.iterator();
167 for (int i = 0; i < size; ++i) {
168 array.set(_length + i, it.next());
169 }
170
171 return array;
172 }
173
174 /**
175 * Return a <i>new</i> {@code Array} with the given {@code values} prepended.
176 *
177 * @since 3.4
178 *
179 * @param values the values to prepend
180 * @return a <i>new</i> {@code Array} with the elements of {@code this}
181 * array and the given {@code values} appended.
182 * @throws NullPointerException if the given {@code values} iterable is
183 * {@code null}
184 */
185 public Array<T> prepend(final Iterable<? extends T> values) {
186 final int size = size(values);
187 final Array<T> array = newInstance(_length + size);
188
189 final Iterator<? extends T> it = values.iterator();
190 for (int i = 0; i < size; ++i) {
191 array.set(i, it.next());
192 }
193
194 for (int i = 0; i < _length; ++i) {
195 array.set(size + i, get(i));
196 }
197
198 return array;
199 }
200
201 private static int size(final Iterable<?> values) {
202 int size = 0;
203 if (values instanceof Collection<?>) {
204 size = ((Collection<?>)values).size();
205 } else {
206 final Iterator<?> it = values.iterator();
207 while (it.hasNext()) {
208 ++size;
209 it.next();
210 }
211 }
212
213 return size;
214 }
215
216 /**
217 * Return the array length.
218 *
219 * @return the array length
220 */
221 public int length() {
222 return _length;
223 }
224
225 /**
226 * Return a copy of this array.
227 *
228 * @return a copy of this array
229 */
230 public Array<T> copy() {
231 return new Array<>(_store.copy(_start, _length + _start));
232 }
233
234 /**
235 * Return a new array slice starting with the {@code from} index.
236 *
237 * @param from the start index
238 * @return a new array slice
239 * @throws ArrayIndexOutOfBoundsException if the index is out of bounds.
240 */
241 public Array<T> slice(final int from) {
242 return slice(from, length());
243 }
244
245 /**
246 * Return a new array slice starting with the {@code from} index and
247 * {@code until} index.
248 *
249 * @param from the start index
250 * @param until the end index
251 * @return a new array slice
252 * @throws ArrayIndexOutOfBoundsException if the indexes are out of bounds.
253 */
254 public Array<T> slice(final int from, final int until) {
255 checkIndex(from, until);
256 return new Array<>(_store, from + _start, until + _start);
257 }
258
259 /**
260 * Check the given array {@code index}
261 *
262 * @param index the index to check
263 * @throws ArrayIndexOutOfBoundsException if the given index is not in the
264 * valid range.
265 */
266 public void checkIndex(final int index) {
267 if (index < 0 || index >= length()) {
268 throw new ArrayIndexOutOfBoundsException(format(
269 "Index %s is out of bounds [0, %s)", index, length()
270 ));
271 }
272 }
273
274 /**
275 * Check the given {@code from} and {@code until} indices.
276 *
277 * @param from the from index, inclusively.
278 * @param until the until index, exclusively.
279 * @throws ArrayIndexOutOfBoundsException if the given index is not in the
280 * valid range.
281 */
282 public final void checkIndex(final int from, final int until) {
283 if (from > until) {
284 throw new ArrayIndexOutOfBoundsException(format(
285 "fromIndex(%d) > toIndex(%d)", from, until
286 ));
287 }
288 if (from < 0 || until > length()) {
289 throw new ArrayIndexOutOfBoundsException(format(
290 "Invalid index range: [%d, %s)", from, until
291 ));
292 }
293 }
294
295 /**
296 * Create a new {@code Array} from the given object store.
297 *
298 * @param store the object store
299 * @param <T> the array type
300 * @return a new array with the given {@code store}
301 */
302 public static <T> Array<T> of(final Store<T> store) {
303 return new Array<>(store);
304 }
305
306 /**
307 * Create a new {@code Array} with the given length. The array is created
308 * with the <i>default</i> {@code ObjectStore} object.
309 *
310 * @param length the array length
311 * @param <T> the array type
312 * @return a new array with the given {@code length}
313 */
314 public static <T> Array<T> ofLength(final int length) {
315 return new Array<T>(ObjectStore.ofLength(length));
316 }
317
318
319 /**
320 * Minimal interface for accessing an underlying array structure.
321 *
322 * @param <T> the array element type
323 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
324 * @version 3.4
325 * @since 3.4
326 */
327 public interface Store<T> {
328
329 /**
330 * Write the given {@code value} at the given {@code index} to the
331 * underlying array structure.
332 *
333 * @param index the array index
334 * @param value the value to set
335 */
336 public void set(final int index, final T value);
337
338 /**
339 * Return the value at the given array {@code index}.
340 *
341 * @param index the array index
342 * @return the value at the given index
343 */
344 public T get(final int index);
345
346 /**
347 * Return the length of the array {@code Store}.
348 *
349 * @return the array store length
350 */
351 public int length();
352
353 /**
354 * Return a new array {@code Store} with the copied portion of the
355 * underlying array.
356 *
357 * @param from the start index of the copied array
358 * @param until the end index of the copied array
359 * @return a new copy of the given range
360 */
361 public Store<T> copy(final int from, final int until);
362
363 /**
364 * Return a new array {@code Store} with the copied portion of the
365 * underlying array.
366 *
367 * @param from the start index of the copied array
368 * @return a new copy of the given range
369 */
370 public default Store<T> copy(final int from) {
371 return copy(from, length());
372 }
373
374 /**
375 * Return a new array {@code Store} copy.
376 *
377 * @return a new array {@code Store} copy
378 */
379 public default Store<T> copy() {
380 return copy(0, length());
381 }
382
383 /**
384 * Return a new {@code Store} of the same type and the given length.
385 *
386 * @param length the length of the new store
387 * @return a new {@code Store} of the same type and the given length.
388 * @throws NegativeArraySizeException if the length is smaller than zero
389 */
390 public Store<T> newInstance(final int length);
391
392 /**
393 * Mutable reference of an underlying array {@code Store}.
394 *
395 * @param <T> the array element type
396 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
397 * @version 3.4
398 * @since 3.4
399 */
400 public static final class Ref<T> implements Store<T>, Serializable {
401 private static final long serialVersionUID = 1L;
402
403 private Store<T> _value;
404 private boolean _sealed;
405
406 /**
407 * Private <i>primary</i> constructor.
408 *
409 * @param value the array store which is referenced
410 * @param sealed the sealed flag of the reference
411 */
412 private Ref(final Store<T> value, final boolean sealed) {
413 _value = value;
414 _sealed = sealed;
415 }
416
417 public Ref<T> seal() {
418 _sealed = true;
419 return new Ref<>(_value, true);
420 }
421
422 public boolean isSealed() {
423 return _sealed;
424 }
425
426 @Override
427 public void set(final int index, final T value) {
428 copyIfSealed();
429 _value.set(index, value);
430 }
431
432 void copyIfSealed() {
433 if (_sealed) {
434 _value = copy();
435 _sealed = false;
436 }
437 }
438
439 @Override
440 public T get(final int index) {
441 return _value.get(index);
442 }
443
444 @Override
445 public int length() {
446 return _value.length();
447 }
448
449 @Override
450 public Store<T> copy(final int from, final int until) {
451 return _value.copy(from, until);
452 }
453
454 @Override
455 public Store<T> newInstance(final int length) {
456 return _value.newInstance(length);
457 }
458
459 public static <T> Ref<T> of(final Store<T> value) {
460 return new Ref<>(requireNonNull(value), false);
461 }
462 }
463
464 }
465
466 }
|