Seq.java
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 <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 <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 <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 <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 }