ArraySeq.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-1.6.0).
003  * Copyright (c) 2007-2014 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.util;
021 
022 import static java.lang.String.format;
023 import static java.lang.System.arraycopy;
024 import static java.util.Arrays.copyOfRange;
025 import static java.util.Objects.requireNonNull;
026 
027 import java.io.IOException;
028 import java.io.ObjectInputStream;
029 import java.io.ObjectOutputStream;
030 import java.io.Serializable;
031 import java.util.Iterator;
032 import java.util.List;
033 
034 /**
035  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
036  @since 1.0
037  @version 1.3 &mdash; <em>$Date: 2013-12-02 $</em>
038  */
039 abstract class ArraySeq<T> implements Seq<T>, Serializable {
040     private static final long serialVersionUID = 1L;
041 
042     transient ArrayRef _array;
043     transient int _start;
044     transient int _end;
045     transient int _length;
046 
047     /**
048      <i>Universal</i> array constructor.
049      *
050      @param array the array which holds the elements. The array will not be
051      *         copied.
052      @param start the start index of the given array (exclusively).
053      @param end the end index of the given array (exclusively)
054      @throws NullPointerException if the given {@code array} is {@code null}.
055      @throws IndexOutOfBoundsException for an illegal start/end point index
056      *          value ({@code start < 0 || end > array.length || start > end}).
057      */
058     ArraySeq(final ArrayRef array, final int start, final int end) {
059         requireNonNull(array, "Array");
060         if (start < || end > array.length || start > end) {
061             throw new ArrayIndexOutOfBoundsException(format(
062                 "Invalid index range: [%d, %s)", start, end
063             ));
064         }
065         _array = array;
066         _start = start;
067         _end = end;
068         _length = _end - _start;
069     }
070 
071     ArraySeq(final int length) {
072         this(new ArrayRef(length)0, length);
073     }
074 
075     @Override
076     @SuppressWarnings("unchecked")
077     public T get(final int index) {
078         checkIndex(index);
079         return (T)_array.data[index + _start];
080     }
081 
082     @Override
083     public int indexOf(final Object element) {
084         return indexOf(element, 0, length());
085     }
086 
087     @Override
088     public int indexOf(final Object element, final int start) {
089         return indexOf(element, start, length());
090     }
091 
092     @Override
093     public int indexOf(final Object element, final int start, final int end) {
094         checkIndex(start, end);
095 
096         final int n = end + _start;
097         int index = -1;
098         if (element == null) {
099             for (int i = start + _start; i < n && index == -1; ++i) {
100                 if (_array.data[i== null) {
101                     index = i - _start;
102                 }
103             }
104         else {
105             for (int i = _start + start; i < n && index == -1; ++i) {
106                 if (element.equals(_array.data[i])) {
107                     index = i - _start;
108                 }
109             }
110         }
111 
112         return index;
113     }
114 
115     @Override
116     public int indexWhere(final Function<? super T, Boolean> predicate) {
117         return indexWhere(predicate, 0, length());
118     }
119 
120     @Override
121     public int indexWhere(
122         final Function<? super T, Boolean> predicate,
123         final int start
124     ) {
125         return indexWhere(predicate, start, length());
126     }
127 
128     @Override
129     public int indexWhere(
130         final Function<? super T, Boolean> predicate,
131         final int start,
132         final int end
133     ) {
134         requireNonNull(predicate, "Predicate");
135 
136         int index = -1;
137 
138         for (int i = start + _start, n = end + _start; i < n && index == -1; ++i) {
139             @SuppressWarnings("unchecked")
140             final T element = (T)_array.data[i];
141 
142             if (predicate.apply(element== Boolean.TRUE) {
143                 index = i - _start;
144             }
145         }
146 
147         return index;
148     }
149 
150     @Override
151     public int lastIndexOf(final Object element) {
152         return lastIndexOf(element, 0, length());
153     }
154 
155     @Override
156     public int lastIndexOf(final Object element, final int end) {
157         return lastIndexOf(element, 0, end);
158     }
159 
160     @Override
161     public int lastIndexOf(final Object element, final int start, final int end) {
162         checkIndex(start, end);
163 
164         int index = -1;
165 
166         if (element == null) {
167             for (int i = end + _start; --i >= start + _start && index == -1;) {
168                 if (_array.data[i== null) {
169                     index = i - _start;
170                 }
171             }
172         else {
173             for (int i = end + _start; --i >= start + _start && index == -1;) {
174                 if (element.equals(_array.data[i])) {
175                     index = i - _start;
176                 }
177             }
178         }
179 
180         return index;
181     }
182 
183     @Override
184     public int lastIndexWhere(final Function<? super T, Boolean> predicate) {
185         return lastIndexWhere(predicate, 0, length());
186     }
187 
188     @Override
189     public int lastIndexWhere(
190         final Function<? super T, Boolean> predicate,
191         final int end
192     ) {
193         return lastIndexWhere(predicate, 0, end);
194     }
195 
196     @Override
197     public int lastIndexWhere(
198         final Function<? super T, Boolean> predicate,
199         final int start,
200         final int end
201     ) {
202         requireNonNull(predicate, "Predicate");
203         checkIndex(start, end);
204 
205         int index = -1;
206 
207         for (int i = end + _start; --i >= start +_start && index == -1;) {
208             @SuppressWarnings("unchecked")
209             final T element = (T)_array.data[i];
210             if (predicate.apply(element== Boolean.TRUE) {
211                 index = i - _start;
212             }
213         }
214 
215         return index;
216     }
217 
218     /**
219      @deprecated Align the naming with the upcoming JDK 1.8 release. Use
220      *             {@link #forEach(Function)} instead.
221      */
222     @Deprecated
223     @Override
224     public <R> void foreach(final Function<? super T, ? extends R> function) {
225         forEach(function);
226     }
227 
228     @Override
229     public <R> void forEach(final Function<? super T, ? extends R> function) {
230         requireNonNull(function, "Function");
231 
232         for (int i = _start; i < _end; ++i) {
233             @SuppressWarnings("unchecked")
234             final T element = (T)_array.data[i];
235             function.apply(element);
236         }
237     }
238 
239     /**
240      @deprecated Align the naming with the upcoming JDK 1.8 release. Use
241      *             {@link #forAll(Function)} instead.
242      */
243     @Deprecated
244     @Override
245     public boolean forall(final Function<? super T, Boolean> predicate) {
246         return forAll(predicate);
247     }
248 
249     @Override
250     public boolean forAll(final Function<? super T, Boolean> predicate) {
251         requireNonNull(predicate, "Predicate");
252 
253         boolean valid = true;
254         for (int i = _start; i < _end && valid; ++i) {
255             @SuppressWarnings("unchecked")
256             final T element = (T)_array.data[i];
257             valid = predicate.apply(element);
258         }
259         return valid;
260     }
261 
262     /*
263     <B> B foldLeft(final B z, final Function2<? super B, ? super T, ? extends B> op) {
264         B result = z;
265         for (int i = 0, n = length(); i < n; ++i) {
266             @SuppressWarnings("unchecked")
267             final T value = (T)_array.data[i + _start];
268             result = op.apply(result, value);
269         }
270         return z;
271     }
272 
273     <B> B foldRight(final B z, final Function2<? super T, ? super B, ? extends B> op) {
274         B result = z;
275         for (int i = length(); --i >= 0;) {
276             @SuppressWarnings("unchecked")
277             final T value = (T)_array.data[i + _start];
278             result = op.apply(value, result);
279         }
280         return z;
281     }
282 
283     interface Function2<T1, T2, R> {
284         R apply(T1 t1, T2 t2);
285     }
286     */
287 
288     @Override
289     public boolean contains(final Object element) {
290         return indexOf(element!= -1;
291     }
292 
293     @Override
294     public int length() {
295         return _length;
296     }
297 
298     @Override
299     public Iterator<T> iterator() {
300         return new ArraySeqIterator<>(this);
301     }
302 
303     @Override
304     public <B> Iterator<B> iterator(
305         final Function<? super T, ? extends B> converter
306     ) {
307         requireNonNull(converter, "Converter");
308 
309         return new Iterator<B>() {
310             private final Iterator<T> _iterator = iterator();
311             @Override public boolean hasNext() {
312                 return _iterator.hasNext();
313             }
314             @Override public B next() {
315                 return converter.apply(_iterator.next());
316             }
317             @Override public void remove() {
318                 _iterator.remove();
319             }
320         };
321     }
322 
323     @Override
324     public Object[] toArray() {
325         Object[] array = null;
326         if (length() == _array.data.length) {
327             array = _array.data.clone();
328         else {
329             array = new Object[length()];
330             arraycopy(_array.data, _start, array, 0, length());
331         }
332 
333         return array;
334     }
335 
336     @SuppressWarnings("unchecked")
337     @Override
338     public T[] toArray(final T[] array) {
339         T[] result = null;
340         if (array.length < length()) {
341             result = (T[])copyOfRange(
342                 _array.data, _start, _end, array.getClass()
343             );
344         else {
345             arraycopy(_array.data, _start, array, 0, length());
346             if (array.length > length()) {
347                 array[length()] null;
348             }
349             result = array;
350         }
351 
352         return result;
353     }
354 
355     @Override
356     public List<T> asList() {
357         return new ArraySeqList<>(this);
358     }
359 
360     final void checkIndex(final int index) {
361         if (index < || index >= _length) {
362             throw new ArrayIndexOutOfBoundsException(format(
363                 "Index %s is out of bounds [0, %s)", index, length()
364             ));
365         }
366     }
367 
368     final void checkIndex(final int from, final int to) {
369         if (from > to) {
370             throw new ArrayIndexOutOfBoundsException(
371                 "fromIndex(" + from + ") > toIndex(" + to+ ")"
372             );
373         }
374         if (from < || to > _length) {
375             throw new ArrayIndexOutOfBoundsException(format(
376                 "Invalid index range: [%d, %s)", from, to
377             ));
378         }
379     }
380 
381     @Override
382     public int hashCode() {
383         return arrays.hashCode(this);
384     }
385 
386     @Override
387     public boolean equals(final Object obj) {
388         return obj == this ||
389                 obj instanceof ArraySeq<?> && arrays.equals(this, obj);
390     }
391 
392     @Override
393     public String toString(
394         final String prefix,
395         final String separator,
396         final String suffix
397     ) {
398           final StringBuilder out = new StringBuilder();
399 
400           out.append(prefix);
401           if (length() 0) {
402             out.append(_array.data[_start]);
403           }
404           for (int i = _start + 1; i < _end; ++i) {
405             out.append(separator);
406             out.append(_array.data[i]);
407           }
408           out.append(suffix);
409 
410           return out.toString();
411     }
412 
413     @Override
414     public String toString(final String separator) {
415         return toString("", separator, "");
416     }
417 
418     @Override
419     public String toString() {
420           return toString("["",""]");
421     }
422 
423     private void writeObject(final ObjectOutputStream out)
424         throws IOException
425     {
426         out.defaultWriteObject();
427 
428         out.writeInt(length());
429         for (int i = _start; i < _end; ++i) {
430             out.writeObject(_array.data[i]);
431         }
432     }
433 
434     private void readObject(final ObjectInputStream in)
435         throws IOException, ClassNotFoundException
436     {
437         in.defaultReadObject();
438 
439         _length = in.readInt();
440         _array = new ArrayRef(_length);
441         _start = 0;
442         _end = _length;
443         for (int i = 0; i < _length; ++i) {
444             _array.data[i= in.readObject();
445         }
446     }
447 
448 }