ArraySeq.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-2.0.2).
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 2.0 &mdash; <em>$Date: 2014-03-10 $</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     @Override
219     public <R> void forEach(final Function<? super T, ? extends R> function) {
220         requireNonNull(function, "Function");
221 
222         for (int i = _start; i < _end; ++i) {
223             @SuppressWarnings("unchecked")
224             final T element = (T)_array.data[i];
225             function.apply(element);
226         }
227     }
228 
229     @Override
230     public boolean forAll(final Function<? super T, Boolean> predicate) {
231         requireNonNull(predicate, "Predicate");
232 
233         boolean valid = true;
234         for (int i = _start; i < _end && valid; ++i) {
235             @SuppressWarnings("unchecked")
236             final T element = (T)_array.data[i];
237             valid = predicate.apply(element);
238         }
239         return valid;
240     }
241 
242     /*
243     <B> B foldLeft(final B z, final Function2<? super B, ? super T, ? extends B> op) {
244         B result = z;
245         for (int i = 0, n = length(); i < n; ++i) {
246             @SuppressWarnings("unchecked")
247             final T value = (T)_array.data[i + _start];
248             result = op.apply(result, value);
249         }
250         return z;
251     }
252 
253     <B> B foldRight(final B z, final Function2<? super T, ? super B, ? extends B> op) {
254         B result = z;
255         for (int i = length(); --i >= 0;) {
256             @SuppressWarnings("unchecked")
257             final T value = (T)_array.data[i + _start];
258             result = op.apply(value, result);
259         }
260         return z;
261     }
262 
263     interface Function2<T1, T2, R> {
264         R apply(T1 t1, T2 t2);
265     }
266     */
267 
268     @Override
269     public boolean contains(final Object element) {
270         return indexOf(element!= -1;
271     }
272 
273     @Override
274     public int length() {
275         return _length;
276     }
277 
278     @Override
279     public Iterator<T> iterator() {
280         return new ArraySeqIterator<>(this);
281     }
282 
283     @Override
284     public <B> Iterator<B> iterator(
285         final Function<? super T, ? extends B> converter
286     ) {
287         requireNonNull(converter, "Converter");
288 
289         return new Iterator<B>() {
290             private final Iterator<T> _iterator = iterator();
291             @Override public boolean hasNext() {
292                 return _iterator.hasNext();
293             }
294             @Override public B next() {
295                 return converter.apply(_iterator.next());
296             }
297             @Override public void remove() {
298                 _iterator.remove();
299             }
300         };
301     }
302 
303     @Override
304     public Object[] toArray() {
305         Object[] array = null;
306         if (length() == _array.data.length) {
307             array = _array.data.clone();
308         else {
309             array = new Object[length()];
310             arraycopy(_array.data, _start, array, 0, length());
311         }
312 
313         return array;
314     }
315 
316     @SuppressWarnings("unchecked")
317     @Override
318     public T[] toArray(final T[] array) {
319         T[] result = null;
320         if (array.length < length()) {
321             result = (T[])copyOfRange(
322                 _array.data, _start, _end, array.getClass()
323             );
324         else {
325             arraycopy(_array.data, _start, array, 0, length());
326             if (array.length > length()) {
327                 array[length()] null;
328             }
329             result = array;
330         }
331 
332         return result;
333     }
334 
335     @Override
336     public List<T> asList() {
337         return new ArraySeqList<>(this);
338     }
339 
340     final void checkIndex(final int index) {
341         if (index < || index >= _length) {
342             throw new ArrayIndexOutOfBoundsException(format(
343                 "Index %s is out of bounds [0, %s)", index, length()
344             ));
345         }
346     }
347 
348     final void checkIndex(final int from, final int to) {
349         if (from > to) {
350             throw new ArrayIndexOutOfBoundsException(
351                 "fromIndex(" + from + ") > toIndex(" + to+ ")"
352             );
353         }
354         if (from < || to > _length) {
355             throw new ArrayIndexOutOfBoundsException(format(
356                 "Invalid index range: [%d, %s)", from, to
357             ));
358         }
359     }
360 
361     @Override
362     public int hashCode() {
363         return arrays.hashCode(this);
364     }
365 
366     @Override
367     public boolean equals(final Object obj) {
368         return obj == this ||
369                 obj instanceof ArraySeq<?> && arrays.equals(this, obj);
370     }
371 
372     @Override
373     public String toString(
374         final String prefix,
375         final String separator,
376         final String suffix
377     ) {
378           final StringBuilder out = new StringBuilder();
379 
380           out.append(prefix);
381           if (length() 0) {
382             out.append(_array.data[_start]);
383           }
384           for (int i = _start + 1; i < _end; ++i) {
385             out.append(separator);
386             out.append(_array.data[i]);
387           }
388           out.append(suffix);
389 
390           return out.toString();
391     }
392 
393     @Override
394     public String toString(final String separator) {
395         return toString("", separator, "");
396     }
397 
398     @Override
399     public String toString() {
400           return toString("["",""]");
401     }
402 
403     private void writeObject(final ObjectOutputStream out)
404         throws IOException
405     {
406         out.defaultWriteObject();
407 
408         out.writeInt(length());
409         for (int i = _start; i < _end; ++i) {
410             out.writeObject(_array.data[i]);
411         }
412     }
413 
414     private void readObject(final ObjectInputStream in)
415         throws IOException, ClassNotFoundException
416     {
417         in.defaultReadObject();
418 
419         _length = in.readInt();
420         _array = new ArrayRef(_length);
421         _start = 0;
422         _end = _length;
423         for (int i = 0; i < _length; ++i) {
424             _array.data[i= in.readObject();
425         }
426     }
427 
428 }