Array.java
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 }