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