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 — <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 < 0 || 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 < 0 || 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 < 0 || 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 }
|