0001 /*
0002 * Java Genetic Algorithm Library (jenetics-5.2.0).
0003 * Copyright (c) 2007-2020 Franz Wilhelmstötter
0004 *
0005 * Licensed under the Apache License, Version 2.0 (the "License");
0006 * you may not use this file except in compliance with the License.
0007 * You may obtain a copy of the License at
0008 *
0009 * http://www.apache.org/licenses/LICENSE-2.0
0010 *
0011 * Unless required by applicable law or agreed to in writing, software
0012 * distributed under the License is distributed on an "AS IS" BASIS,
0013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014 * See the License for the specific language governing permissions and
0015 * limitations under the License.
0016 *
0017 * Author:
0018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
0019 */
0020 package io.jenetics.util;
0021
0022 import static java.util.Objects.requireNonNull;
0023 import static java.util.stream.Collectors.joining;
0024 import static io.jenetics.internal.collection.Array.checkIndex;
0025
0026 import java.util.ArrayList;
0027 import java.util.Arrays;
0028 import java.util.Comparator;
0029 import java.util.Iterator;
0030 import java.util.List;
0031 import java.util.Objects;
0032 import java.util.RandomAccess;
0033 import java.util.function.Function;
0034 import java.util.function.IntFunction;
0035 import java.util.function.Predicate;
0036 import java.util.function.Supplier;
0037 import java.util.stream.Collector;
0038 import java.util.stream.Stream;
0039 import java.util.stream.StreamSupport;
0040
0041 /**
0042 * General interface for a ordered, fixed sized, object sequence.
0043 * <br>
0044 * Use the {@link #asList()} method to work together with the
0045 * <a href="http://download.oracle.com/javase/6/docs/technotes/guides/collections/index.html">
0046 * Java Collection Framework</a>.
0047 *
0048 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0049 * @since 1.0
0050 * @version 5.2
0051 */
0052 public interface Seq<T> extends BaseSeq<T>, IntFunction<T> {
0053
0054 /**
0055 * Return the value at the given {@code index}.
0056 *
0057 * @since 3.9
0058 *
0059 * @see #get(int)
0060 *
0061 * @param index index of the element to return.
0062 * @return the value at the given {@code index}.
0063 * @throws IndexOutOfBoundsException if the index is out of range
0064 * {@code index < 0 || index >= size()}.
0065 */
0066 @Override
0067 default T apply(final int index) {
0068 return get(index);
0069 }
0070
0071 /**
0072 * @see #length()
0073 * @return the size of this sequence
0074 */
0075 default int size() {
0076 return length();
0077 }
0078
0079 /**
0080 * Returns {@code true} if this sequence contains no elements.
0081 *
0082 * @since 3.3
0083 *
0084 * @return {@code true} if this sequence contains no elements
0085 */
0086 default boolean isEmpty() {
0087 return length() == 0;
0088 }
0089
0090 /**
0091 * Returns {@code true} if this sequence contains at least one element.
0092 *
0093 * @since 4.0
0094 *
0095 * @return {@code true} if this sequence contains at least one element
0096 */
0097 default boolean nonEmpty() {
0098 return !isEmpty();
0099 }
0100
0101 /**
0102 * Tests whether a predicate holds for all elements of this sequence.
0103 *
0104 * @param predicate the predicate to use to test the elements.
0105 * @return {@code true} if the given predicate p holds for all elements of
0106 * this sequence, {@code false} otherwise.
0107 * @throws NullPointerException if the given {@code predicate} is
0108 * {@code null}.
0109 */
0110 default boolean forAll(final Predicate<? super T> predicate) {
0111 boolean valid = true;
0112
0113 if (this instanceof RandomAccess) {
0114 for (int i = 0, n = length(); i < n && valid; ++i) {
0115 valid = predicate.test(get(i));
0116 }
0117 } else {
0118 final Iterator<T> it = iterator();
0119 while (it.hasNext() && valid) {
0120 valid = predicate.test(it.next());
0121 }
0122 }
0123
0124 return valid;
0125 }
0126
0127 /**
0128 * Returns a possibly parallel {@code Stream} with this sequence as its
0129 * source. It is allowable for this method to return a sequential stream.
0130 *
0131 * @since 3.0
0132 *
0133 * @return a possibly parallel {@code Stream} over the elements in this
0134 * collection
0135 */
0136 default Stream<T> parallelStream() {
0137 return StreamSupport.stream(spliterator(), true);
0138 }
0139
0140 /**
0141 * Returns {@code true} if this sequence contains the specified element.
0142 *
0143 * @param element element whose presence in this sequence is to be tested.
0144 * The tested element can be {@code null}.
0145 * @return {@code true} if this sequence contains the specified element
0146 */
0147 default boolean contains(final Object element) {
0148 return indexOf(element) != -1;
0149 }
0150
0151 /**
0152 * Returns the index of the first occurrence of the specified element
0153 * in this sequence, or -1 if this sequence does not contain the element.
0154 *
0155 * @param element element to search for, can be {@code null}
0156 * @return the index of the first occurrence of the specified element in
0157 * this sequence, or -1 if this sequence does not contain the element
0158 */
0159 default int indexOf(final Object element) {
0160 return indexOf(element, 0, length());
0161 }
0162
0163 /**
0164 * Returns the index of the first occurrence of the specified element
0165 * in this sequence, or -1 if this sequence does not contain the element.
0166 *
0167 * @param element element to search for, can be {@code null}
0168 * @param start the start index (inclusively) for the element search.
0169 * @return the index of the first occurrence of the specified element in
0170 * this sequence, or -1 if this sequence does not contain the element
0171 * @throws IndexOutOfBoundsException for an illegal end point index value
0172 * ({@code start < 0 || start > length()}).
0173 */
0174 default int indexOf(final Object element, final int start) {
0175 return indexOf(element, start, length());
0176 }
0177
0178 /**
0179 * Returns the index of the first occurrence of the specified element
0180 * in this sequence, or -1 if this sequence does not contain the element.
0181 *
0182 * @param element element to search for, can be {@code null}
0183 * @param start the start index (inclusively) for the element search.
0184 * @param end the end index (exclusively) for the element search.
0185 * @return the index of the first occurrence of the specified element in
0186 * this sequence, or -1 if this sequence does not contain the element
0187 * @throws IndexOutOfBoundsException for an illegal end point index value
0188 * ({@code start < 0 || end > length() || start > end}).
0189 */
0190 default int indexOf(final Object element, final int start, final int end) {
0191 return element != null
0192 ? indexWhere(element::equals, start, end)
0193 : indexWhere(Objects::isNull, start, end);
0194 }
0195
0196 /**
0197 * <p>
0198 * Returns the index of the first element on which the given predicate
0199 * returns {@code true}, or -1 if the predicate returns false for every
0200 * sequence element.
0201 * </p>
0202 * <pre>{@code
0203 * // Finding index of first null value.
0204 * final int index = seq.indexOf(o -> o == null);
0205 *
0206 * // Assert of no null values.
0207 * assert (sequence.indexOf(o -> o == null) == -1);
0208 * }</pre>
0209 *
0210 * @param predicate the search predicate.
0211 * @return the index of the first element on which the given predicate
0212 * returns {@code true}, or -1 if the predicate returns {@code false}
0213 * for every sequence element.
0214 * @throws NullPointerException if the given {@code predicate} is {@code null}.
0215 */
0216 default int indexWhere(final Predicate<? super T> predicate) {
0217 return indexWhere(predicate, 0, length());
0218 }
0219
0220 /**
0221 * <p>
0222 * Returns the index of the first element on which the given predicate
0223 * returns {@code true}, or -1 if the predicate returns false for every
0224 * sequence element.
0225 * </p>
0226 * <pre>{@code
0227 * // Finding index of first null value.
0228 * final int index = seq.indexOf(o -> o == null);
0229 *
0230 * // Assert of no null values.
0231 * assert (sequence.indexOf(o -> o == null) == -1);
0232 * }</pre>
0233 *
0234 * @param predicate the search predicate.
0235 * @param start the search start index
0236 * @return the index of the first element on which the given predicate
0237 * returns {@code true}, or -1 if the predicate returns {@code false}
0238 * for every sequence element.
0239 * @throws NullPointerException if the given {@code predicate} is {@code null}.
0240 * @throws IndexOutOfBoundsException for an illegal end point index value
0241 * ({@code start < 0 || start > length()}).
0242 */
0243 default int indexWhere(
0244 final Predicate<? super T> predicate,
0245 final int start
0246 ) {
0247 return indexWhere(predicate, start, length());
0248 }
0249
0250 /**
0251 * <p>
0252 * Returns the index of the first element on which the given predicate
0253 * returns {@code true}, or -1 if the predicate returns false for every
0254 * sequence element.
0255 * </p>
0256 * <pre>{@code
0257 * // Finding index of first null value.
0258 * final int index = seq.indexOf(o -> o == null);
0259 *
0260 * // Assert of no null values.
0261 * assert (sequence.indexOf(o -> o == null) == -1);
0262 * }</pre>
0263 *
0264 * @param predicate the search predicate.
0265 * @param start the search start index
0266 * @param end the search end index
0267 * @return the index of the first element on which the given predicate
0268 * returns {@code true}, or -1 if the predicate returns {@code false}
0269 * for every sequence element.
0270 * @throws NullPointerException if the given {@code predicate} is {@code null}.
0271 * @throws IndexOutOfBoundsException for an illegal end point index value
0272 * ({@code start < 0 || end > length() || start > end}).
0273 */
0274 default int indexWhere(
0275 final Predicate<? super T> predicate,
0276 final int start,
0277 final int end
0278 ) {
0279 requireNonNull(predicate, "Predicate");
0280 checkIndex(start, end, length());
0281
0282 int index = -1;
0283 for (int i = start; i < end && index == -1; ++i) {
0284 if (predicate.test(get(i))) {
0285 index = i;
0286 }
0287 }
0288 return index;
0289 }
0290
0291 /**
0292 * Returns the index of the last occurrence of the specified element
0293 * in this sequence, or -1 if this sequence does not contain the element.
0294 *
0295 * @param element element to search for, can be {@code null}
0296 * @return the index of the last occurrence of the specified element in
0297 * this sequence, or -1 if this sequence does not contain the element
0298 */
0299 default int lastIndexOf(final Object element) {
0300 return lastIndexOf(element, 0, length());
0301 }
0302
0303 /**
0304 * Returns the index of the last occurrence of the specified element
0305 * in this sequence, or -1 if this sequence does not contain the element.
0306 *
0307 * @param element element to search for, can be {@code null}
0308 * @param end the search end index
0309 * @return the index of the last occurrence of the specified element in
0310 * this sequence, or -1 if this sequence does not contain the element
0311 * @throws IndexOutOfBoundsException for an illegal end point index value
0312 * ({@code end < 0 || end > length()}).
0313 */
0314 default int lastIndexOf(final Object element, final int end) {
0315 return lastIndexOf(element, 0, end);
0316 }
0317
0318 /**
0319 * Returns the index of the last occurrence of the specified element
0320 * in this sequence, or -1 if this sequence does not contain the element.
0321 *
0322 * @param element element to search for, can be {@code null}
0323 * @param start the search start index
0324 * @param end the search end index
0325 * @return the index of the last occurrence of the specified element in
0326 * this sequence, or -1 if this sequence does not contain the element
0327 * @throws IndexOutOfBoundsException for an illegal end point index value
0328 * ({@code start < 0 || end > length() || start > end}).
0329 */
0330 default int lastIndexOf(
0331 final Object element,
0332 final int start,
0333 final int end
0334 ) {
0335 return element != null
0336 ? lastIndexWhere(element::equals, start, end)
0337 : lastIndexWhere(Objects::isNull, start, end);
0338 }
0339
0340 /**
0341 * Returns the index of the last element on which the given predicate
0342 * returns {@code true}, or -1 if the predicate returns false for every
0343 * sequence element.
0344 *
0345 * @param predicate the search predicate.
0346 * @return the index of the last element on which the given predicate
0347 * returns {@code true}, or -1 if the predicate returns false for
0348 * every sequence element.
0349 * @throws NullPointerException if the given {@code predicate} is {@code null}.
0350 */
0351 default int lastIndexWhere(final Predicate<? super T> predicate) {
0352 return lastIndexWhere(predicate, 0, length());
0353 }
0354
0355 /**
0356 * Returns the index of the last element on which the given predicate
0357 * returns {@code true}, or -1 if the predicate returns false for every
0358 * sequence element.
0359 *
0360 * @param predicate the search predicate.
0361 * @param end the search end index
0362 * @return the index of the last element on which the given predicate
0363 * returns {@code true}, or -1 if the predicate returns false for
0364 * every sequence element.
0365 * @throws NullPointerException if the given {@code predicate} is {@code null}.
0366 * @throws IndexOutOfBoundsException for an illegal end point index value
0367 * ({@code end < 0 || end > length()}).
0368 */
0369 default int lastIndexWhere(
0370 final Predicate<? super T> predicate,
0371 final int end
0372 ) {
0373 return lastIndexWhere(predicate, 0, end);
0374 }
0375
0376 /**
0377 * Returns the index of the last element on which the given predicate
0378 * returns {@code true}, or -1 if the predicate returns false for every
0379 * sequence element.
0380 *
0381 * @param predicate the search predicate.
0382 * @param start the search start index
0383 * @param end the search end index
0384 * @return the index of the last element on which the given predicate
0385 * returns {@code true}, or -1 if the predicate returns false for
0386 * every sequence element.
0387 * @throws NullPointerException if the given {@code predicate} is {@code null}.
0388 * @throws IndexOutOfBoundsException for an illegal end point index value
0389 * ({@code start < 0 || end > length() || start > end}).
0390 */
0391 default int lastIndexWhere(
0392 final Predicate<? super T> predicate,
0393 final int start,
0394 final int end
0395 ) {
0396 requireNonNull(predicate, "Predicate");
0397 checkIndex(start, end, length());
0398
0399 int index = -1;
0400 for (int i = end; --i >= start && index == -1;) {
0401 if (predicate.test(get(i))) {
0402 index = i;
0403 }
0404 }
0405 return index;
0406 }
0407
0408 /**
0409 * Builds a new sequence by applying a function to all elements of this
0410 * sequence.
0411 *
0412 * @param <B> the element type of the returned collection.
0413 * @param mapper the function to apply to each element.
0414 * @return a new sequence of type That resulting from applying the given
0415 * function f to each element of this sequence and collecting the
0416 * results.
0417 * @throws NullPointerException if the element {@code mapper} is
0418 * {@code null}.
0419 */
0420 <B> Seq<B> map(final Function<? super T, ? extends B> mapper);
0421
0422 /**
0423 * Return a <i>new</i> {@code Seq} with the given {@code values} appended.
0424 *
0425 * @since 3.4
0426 *
0427 * @param values the values to append
0428 * @return a <i>new</i> {@code Seq} with the elements of {@code this}
0429 * sequence and the given {@code values} appended.
0430 * @throws NullPointerException if the given {@code values} array is
0431 * {@code null}
0432 */
0433 @SuppressWarnings("unchecked")
0434 default Seq<T> append(final T... values) {
0435 return append(Seq.of(values));
0436 }
0437
0438 /**
0439 * Return a <i>new</i> {@code Seq} with the given {@code values} appended.
0440 *
0441 * @since 3.4
0442 *
0443 * @param values the values to append
0444 * @return a <i>new</i> {@code Seq} with the elements of {@code this}
0445 * sequence and the given {@code values} appended.
0446 * @throws NullPointerException if the given {@code values} iterable is
0447 * {@code null}
0448 */
0449 Seq<T> append(final Iterable<? extends T> values);
0450
0451 /**
0452 * Return a <i>new</i> {@code Seq} with the given {@code values} prepended.
0453 *
0454 * @since 3.4
0455 *
0456 * @param values the values to append
0457 * @return a <i>new</i> {@code Seq} with the elements of {@code this}
0458 * sequence and the given {@code values} prepended.
0459 * @throws NullPointerException if the given {@code values} array is
0460 * {@code null}
0461 */
0462 @SuppressWarnings("unchecked")
0463 default Seq<T> prepend(final T... values) {
0464 return prepend(Seq.of(values));
0465 }
0466
0467 /**
0468 * Return a <i>new</i> {@code Seq} with the given {@code values} prepended.
0469 *
0470 * @since 3.4
0471 *
0472 * @param values the values to append
0473 * @return a <i>new</i> {@code Seq} with the elements of {@code this}
0474 * sequence and the given {@code values} prepended.
0475 * @throws NullPointerException if the given {@code values} array is
0476 * {@code null}
0477 */
0478 Seq<T> prepend(final Iterable<? extends T> values);
0479
0480 /**
0481 * Returns a fixed-size list backed by the specified sequence. (Changes to
0482 * the returned list "write through" to the array.) The returned list is
0483 * fixed size, serializable and implements {@link RandomAccess}.
0484 *
0485 * @return a list view of this sequence
0486 */
0487 default List<T> asList() {
0488 return new SeqList<>(this);
0489 }
0490
0491 /**
0492 * Return an array containing all of the elements in this sequence in right
0493 * order. The returned array will be "safe" in that no references to it
0494 * are maintained by this sequence. (In other words, this method must allocate
0495 * a new array.) The caller is thus free to modify the returned array.
0496 *
0497 * @see java.util.Collection#toArray()
0498 *
0499 * @return an array containing all of the elements in this list in right
0500 * order
0501 */
0502 default Object[] toArray() {
0503 final Object[] array = new Object[size()];
0504 for (int i = size(); --i >= 0;) {
0505 array[i] = get(i);
0506 }
0507 return array;
0508 }
0509
0510 /**
0511 * Return an array containing all of the elements in this sequence in right
0512 * order; the runtime type of the returned array is that of the specified
0513 * array. If this sequence fits in the specified array, it is returned
0514 * therein. Otherwise, a new array is allocated with the runtime type of the
0515 * specified array and the length of this array.
0516 * <p>
0517 * If this sequence fits in the specified array with room to spare (i.e.,
0518 * the array has more elements than this array), the element in the array
0519 * immediately following the end of this array is set to null. (This is
0520 * useful in determining the length of the array only if the caller knows
0521 * that the list does not contain any null elements.)
0522 *
0523 * @see java.util.Collection#toArray(Object[])
0524 *
0525 * @param <B> the runtime type of the array to contain the sequence
0526 * @param array the array into which the elements of this array are to be
0527 * stored, if it is big enough; otherwise, a new array of the same
0528 * runtime type is allocated for this purpose.
0529 * @return an array containing the elements of this array
0530 * @throws ArrayStoreException if the runtime type of the specified array is
0531 * not a super type of the runtime type of every element in this
0532 * array
0533 * @throws NullPointerException if the given {@code array} is {@code null}.
0534 */
0535 @SuppressWarnings("unchecked")
0536 default <B> B[] toArray(final B[] array) {
0537 if (array.length < length()) {
0538 final Object[] copy = (Object[])java.lang.reflect.Array
0539 .newInstance(array.getClass().getComponentType(), length());
0540
0541 for (int i = length(); --i >= 0;) {
0542 copy[i] = get(i);
0543 }
0544
0545 return (B[])copy;
0546 }
0547
0548 for (int i = 0, n = length(); i < n; ++i) {
0549 ((Object[])array)[i] = get(i);
0550 }
0551 if (array.length > length()) {
0552 array[length()] = null;
0553 }
0554
0555 return array;
0556 }
0557
0558 /**
0559 * Returns an array containing the elements of this sequence, using the
0560 * provided generator function to allocate the returned array.
0561 *
0562 * @since 4.4
0563 *
0564 * @param generator a function which produces a new array of the desired
0565 * type and the provided length
0566 * @param <B> the element type of the resulting array
0567 * @return an array containing the elements in {@code this} sequence
0568 * @throws ArrayStoreException if the runtime type of the specified array is
0569 * not a super type of the runtime type of every element in this
0570 * array
0571 * @throws NullPointerException if the given {@code generator} is {@code null}.
0572 */
0573 default <B> B[] toArray(final IntFunction<B[]> generator) {
0574 return toArray(generator.apply(length()));
0575 }
0576
0577 /**
0578 * Returns a view of the portion of this sequence between the specified
0579 * {@code start}, inclusive, and {@code end}, exclusive. (If {@code start}
0580 * and {@code end} are equal, the returned sequence has the length zero.)
0581 * The returned sequence is backed by this sequence, so non-structural
0582 * changes in the returned sequence are reflected in this sequence, and
0583 * vice-versa.
0584 * <p>
0585 * This method eliminates the need for explicit range operations (of the
0586 * populationSort that commonly exist for arrays). Any operation that
0587 * expects an sequence can be used as a range operation by passing an sub
0588 * sequence view instead of an whole sequence.
0589 *
0590 * @param start low end point (inclusive) of the sub array.
0591 * @return a view of the specified range within this array.
0592 * @throws IndexOutOfBoundsException for an illegal end point index value
0593 * ({@code start < 0 || start > length()}).
0594 */
0595 Seq<T> subSeq(final int start);
0596
0597 /**
0598 * Returns a view of the portion of this sequence between the specified
0599 * {@code start}, inclusive, and {@code end}, exclusive. (If {@code start}
0600 * and {@code end} are equal, the returned sequence has the length zero.)
0601 * The returned sequence is backed by this sequence, so non-structural
0602 * changes in the returned sequence are reflected in this array, and
0603 * vice-versa.
0604 * <p>
0605 * This method eliminates the need for explicit range operations (of the
0606 * populationSort that commonly exist for arrays). Any operation that
0607 * expects an array can be used as a range operation by passing an sub
0608 * sequence view instead of an whole sequence.
0609 *
0610 * @param start low end point (inclusive) of the sub sequence.
0611 * @param end high end point (exclusive) of the sub sequence.
0612 * @return a view of the specified range within this sequence.
0613 * @throws IndexOutOfBoundsException for an illegal end point index value
0614 * ({@code start < 0 || end > length() || start > end}).
0615 */
0616 public Seq<T> subSeq(final int start, final int end);
0617
0618 /**
0619 * Test whether the given array is sorted in ascending order.
0620 *
0621 * @return {@code true} if the given {@code array} is sorted in ascending
0622 * order, {@code false} otherwise.
0623 * @throws NullPointerException if the given array or one of it's element is
0624 * {@code null}.
0625 */
0626 @SuppressWarnings("unchecked")
0627 default boolean isSorted() {
0628 boolean sorted = true;
0629 for (int i = 0, n = length() - 1; i < n && sorted; ++i) {
0630 sorted = ((Comparable<T>)get(i)).compareTo(get(i + 1)) <= 0;
0631 }
0632
0633 return sorted;
0634 }
0635
0636 /**
0637 * Test whether the given array is sorted in ascending order. The order of
0638 * the array elements is defined by the given comparator.
0639 *
0640 * @param comparator the comparator which defines the order.
0641 * @return {@code true} if the given {@code array} is sorted in ascending
0642 * order, {@code false} otherwise.
0643 * @throws NullPointerException if the given array or one of it's element or
0644 * the comparator is {@code null}.
0645 */
0646 default boolean isSorted(final Comparator<? super T> comparator) {
0647 boolean sorted = true;
0648 for (int i = 0, n = length() - 1; i < n && sorted; ++i) {
0649 sorted = comparator.compare(get(i), get(i + 1)) <= 0;
0650 }
0651
0652 return sorted;
0653 }
0654
0655 /**
0656 * Return this sequence as {@code MSeq} instance. If {@code this} is not a
0657 * {@code MSeq} a new seq is created.
0658 *
0659 * @since 3.8
0660 *
0661 * @return a {@code MSeq} with this values
0662 */
0663 default MSeq<T> asMSeq() {
0664 return this instanceof MSeq ? (MSeq<T>)this : MSeq.of(this);
0665 }
0666
0667 /**
0668 * Return this sequence as {@code ISeq} instance. If {@code this} is not a
0669 * {@code ISeq} a new seq is created.
0670 *
0671 * @since 3.8
0672 *
0673 * @return a {@code ISeq} with this values
0674 */
0675 default ISeq<T> asISeq() {
0676 return this instanceof ISeq ? (ISeq<T>)this : ISeq.of(this);
0677 }
0678
0679 /**
0680 * Returns the hash code value for this sequence. The hash code is defined
0681 * as followed:
0682 *
0683 * <pre>{@code
0684 * int hashCode = 1;
0685 * final Iterator<E> it = seq.iterator();
0686 * while (it.hasNext()) {
0687 * final E obj = it.next();
0688 * hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
0689 * }
0690 * }</pre>
0691 *
0692 * @see List#hashCode()
0693 * @see Seq#hashCode(BaseSeq)
0694 *
0695 * @return the hash code value for this list
0696 */
0697 @Override
0698 int hashCode();
0699
0700 /**
0701 * Compares the specified object with this sequence for equality. Returns
0702 * true if and only if the specified object is also a sequence, both
0703 * sequence have the same size, and all corresponding pairs of elements in
0704 * the two sequences are equal. (Two elements e1 and e2 are equal if
0705 * (e1==null ? e2==null : e1.equals(e2)).) This definition ensures that the
0706 * equals method works properly across different implementations of the Seq
0707 * interface.
0708 *
0709 * @see List#equals(Object)
0710 * @see Seq#equals(BaseSeq, Object)
0711 *
0712 * @param object the object to be compared for equality with this sequence.
0713 * @return {@code true} if the specified object is equal to this sequence,
0714 * {@code false} otherwise.
0715 */
0716 @Override
0717 boolean equals(final Object object);
0718
0719 /**
0720 * Create a string representation of the given sequence.
0721 *
0722 * @param prefix the prefix of the string representation; e.g {@code '['}.
0723 * @param separator the separator of the array elements; e.g. {@code ','}.
0724 * @param suffix the suffix of the string representation; e.g. {@code ']'}.
0725 * @return the string representation of this sequence.
0726 */
0727 default String toString(
0728 final String prefix,
0729 final String separator,
0730 final String suffix
0731 ) {
0732 return stream()
0733 .map(Objects::toString)
0734 .collect(joining(separator, prefix, suffix));
0735 }
0736
0737 /**
0738 * Create a string representation of the given sequence.
0739 *
0740 * @param separator the separator of the array elements; e.g. {@code ','}.
0741 * @return the string representation of this sequence.
0742 */
0743 default String toString(final String separator) {
0744 return toString("", separator, "");
0745 }
0746
0747 /**
0748 * Unified method for calculating the hash code of every {@link Seq}
0749 * implementation. The hash code is defined as followed:
0750 *
0751 * <pre>{@code
0752 * int hashCode = 1;
0753 * final Iterator<E> it = seq.iterator();
0754 * while (it.hasNext()) {
0755 * final E obj = it.next();
0756 * hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
0757 * }
0758 * }</pre>
0759 *
0760 * @see Seq#hashCode()
0761 * @see List#hashCode()
0762 *
0763 * @param seq the sequence to calculate the hash code for.
0764 * @return the hash code of the given sequence.
0765 */
0766 static int hashCode(final BaseSeq<?> seq) {
0767 int hash = 1;
0768 for (Object element : seq) {
0769 hash = 31*hash + (element == null ? 0: element.hashCode());
0770 }
0771 return hash;
0772 }
0773
0774 /**
0775 * Unified method for compare to sequences for equality.
0776 *
0777 * @see Seq#equals(Object)
0778 *
0779 * @param seq the sequence to test for equality.
0780 * @param obj the object to test for equality with the sequence.
0781 * @return {@code true} if the given objects are sequences and contain the
0782 * same objects in the same order, {@code false} otherwise.
0783 */
0784 static boolean equals(final BaseSeq<?> seq, final Object obj) {
0785 if (obj == seq) {
0786 return true;
0787 }
0788 if (!(obj instanceof Seq)) {
0789 return false;
0790 }
0791
0792 final Seq<?> other = (Seq<?>)obj;
0793 boolean equals = seq.length() == other.length();
0794 for (int i = seq.length(); equals && --i >= 0;) {
0795 final Object element = seq.get(i);
0796 equals = element != null
0797 ? element.equals(other.get(i))
0798 : other.get(i) == null;
0799 }
0800 return equals;
0801 }
0802
0803 /* *************************************************************************
0804 * Some static helper methods.
0805 * ************************************************************************/
0806
0807 /**
0808 * Return a sequence whose elements are all the elements of the first
0809 * element followed by all the elements of the sequence.
0810 *
0811 * @since 5.0
0812 *
0813 * @param a the first element
0814 * @param b the appending sequence
0815 * @param <T> the type of the sequence elements
0816 * @return the concatenation of the two inputs
0817 * @throws NullPointerException if one of the second arguments is
0818 * {@code null}
0819 */
0820 @SuppressWarnings("unchecked")
0821 static <T> Seq<T> concat(
0822 final T a,
0823 final Seq<? extends T> b
0824 ) {
0825 return ((Seq<T>)b).prepend(a);
0826 }
0827
0828 /**
0829 * Return a sequence whose elements are all the elements of the first
0830 * sequence followed by all the elements of the vararg array.
0831 *
0832 * @since 5.0
0833 *
0834 * @param a the first sequence
0835 * @param b the vararg elements
0836 * @param <T> the type of the sequence elements
0837 * @return the concatenation of the two inputs
0838 * @throws NullPointerException if one of the arguments is {@code null}
0839 */
0840 @SuppressWarnings("unchecked")
0841 static <T> Seq<T> concat(
0842 final Seq<? extends T> a,
0843 final T... b
0844 ) {
0845 return ((Seq<T>)a).append(b);
0846 }
0847
0848 /**
0849 * Return a sequence whose elements are all the elements of the first
0850 * sequence followed by all the elements of the second sequence.
0851 *
0852 * @since 5.0
0853 *
0854 * @param a the first sequence
0855 * @param b the second sequence
0856 * @param <T> the type of the sequence elements
0857 * @return the concatenation of the two input sequences
0858 * @throws NullPointerException if one of the arguments is {@code null}
0859 */
0860 @SuppressWarnings("unchecked")
0861 static <T> Seq<T> concat(
0862 final Seq<? extends T> a,
0863 final Seq<? extends T> b
0864 ) {
0865 return ((Seq<T>)a).append(b);
0866 }
0867
0868 /* *************************************************************************
0869 * Some static factory methods.
0870 * ************************************************************************/
0871
0872 /**
0873 * Single instance of an empty {@code Seq}.
0874 *
0875 * @since 3.3
0876 */
0877 Seq<?> EMPTY = ISeq.EMPTY;
0878
0879 /**
0880 * Return an empty {@code Seq}.
0881 *
0882 * @since 3.3
0883 *
0884 * @param <T> the element type of the returned {@code Seq}.
0885 * @return an empty {@code Seq}.
0886 */
0887 static <T> Seq<T> empty() {
0888 return ISeq.empty();
0889 }
0890
0891 /**
0892 * Returns a {@code Collector} that accumulates the input elements into a
0893 * new {@code Seq}.
0894 *
0895 * @param <T> the type of the input elements
0896 * @return a {@code Collector} which collects all the input elements into a
0897 * {@code Seq}, in encounter order
0898 */
0899 static <T> Collector<T, ?, Seq<T>> toSeq() {
0900 return Collector.of(
0901 (Supplier<List<T>>)ArrayList::new,
0902 List::add,
0903 (left, right) -> { left.addAll(right); return left; },
0904 Seq::of
0905 );
0906 }
0907
0908 /**
0909 * Returns a {@code Collector} that accumulates the last {@code n} input
0910 * elements into a new {@code Seq}.
0911 *
0912 * @since 5.0
0913 *
0914 * @param maxSize the maximal size of the collected sequence
0915 * @param <T> the type of the input elements
0916 * @return a {@code Collector} which collects maximal {@code maxSize} of the
0917 * input elements into an {@code ISeq}, in encounter order
0918 * @throws IllegalArgumentException if the {@code maxSize} is negative
0919 */
0920 static <T> Collector<T, ?, Seq<T>> toSeq(final int maxSize) {
0921 return Seqs.toSeq(maxSize, Buffer::toSeq);
0922 }
0923
0924 /**
0925 * Create a new {@code Seq} from the given values.
0926 *
0927 * @param <T> the element type
0928 * @param values the array values.
0929 * @return a new {@code Seq} with the given values.
0930 * @throws NullPointerException if the {@code values} array is {@code null}.
0931 */
0932 @SafeVarargs
0933 static <T> Seq<T> of(final T... values) {
0934 return ISeq.of(values);
0935 }
0936
0937 /**
0938 * Create a new {@code Seq} from the given values.
0939 *
0940 * @param <T> the element type
0941 * @param values the array values.
0942 * @return a new {@code Seq} with the given values.
0943 * @throws NullPointerException if the {@code values} array is {@code null}.
0944 */
0945 static <T> Seq<T> of(final Iterable<? extends T> values) {
0946 return ISeq.of(values);
0947 }
0948
0949 /**
0950 * Creates a new sequence, which is filled with objects created be the given
0951 * {@code supplier}.
0952 *
0953 * @since 3.3
0954 *
0955 * @param <T> the element type of the sequence
0956 * @param supplier the {@code Supplier} which creates the elements, the
0957 * returned sequence is filled with
0958 * @param length the length of the returned sequence
0959 * @return a new sequence filled with elements given by the {@code supplier}
0960 * @throws NegativeArraySizeException if the given {@code length} is
0961 * negative
0962 * @throws NullPointerException if the given {@code supplier} is
0963 * {@code null}
0964 */
0965 static <T> Seq<T> of(Supplier<? extends T> supplier, final int length) {
0966 return ISeq.of(supplier, length);
0967 }
0968
0969
0970 /**
0971 * Returns a sequence backed by the specified list. (Changes to the given
0972 * list are "write through" to the returned sequence.) This method acts
0973 * as bridge between collection-based and sequence-based APIs.
0974 *
0975 * @since 4.2
0976 *
0977 * @param list the list containing the elements
0978 * @param <T> the element type
0979 * @return a sequence view of the given {@code list}
0980 * @throws NullPointerException if the given list is {@code null}
0981 */
0982 static <T> Seq<T> viewOf(final List<? extends T> list) {
0983 return list.isEmpty()
0984 ? empty()
0985 : new SeqView<>(list);
0986 }
0987
0988 /**
0989 * Returns a fixed-size sequence backed by the specified array. (Changes to
0990 * the given array are "write through" to the returned sequence.) This
0991 * method acts as bridge between array-based and sequence-based APIs.
0992 *
0993 * @since 4.2
0994 *
0995 * @param array the array containing the sequence elements
0996 * @param <T> the element type
0997 * @return a sequence view of the given {@code array}
0998 * @throws NullPointerException if the given array is {@code null}
0999 */
1000 static <T> Seq<T> viewOf(final T[] array) {
1001 return array.length == 0
1002 ? empty()
1003 : new SeqView<>(Arrays.asList(array));
1004 }
1005
1006 }
|