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