001/*
002 * Java Genetic Algorithm Library (jenetics-7.1.0).
003 * Copyright (c) 2007-2022 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.util;
021
022import static java.util.Objects.requireNonNull;
023import static java.util.stream.Collectors.joining;
024import static io.jenetics.internal.collection.Array.checkIndex;
025
026import java.util.ArrayList;
027import java.util.Arrays;
028import java.util.Comparator;
029import java.util.List;
030import java.util.Objects;
031import java.util.RandomAccess;
032import java.util.function.Function;
033import java.util.function.IntFunction;
034import java.util.function.Predicate;
035import java.util.function.Supplier;
036import java.util.stream.Collector;
037import java.util.stream.Stream;
038import java.util.stream.StreamSupport;
039
040/**
041 * General interface for a ordered, fixed sized, object sequence.
042 * <br>
043 * Use the {@link #asList()} method to work together with the
044 * <a href="http://download.oracle.com/javase/6/docs/technotes/guides/collections/index.html">
045 * Java Collection Framework</a>.
046 *
047 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
048 * @since 1.0
049 * @version 5.2
050 */
051public interface Seq<T> extends BaseSeq<T>, IntFunction<T> {
052
053        /**
054         * Return the value at the given {@code index}.
055         *
056         * @since 3.9
057         *
058         * @see #get(int)
059         *
060         * @param index index of the element to return.
061         * @return the value at the given {@code index}.
062         * @throws IndexOutOfBoundsException if the index is out of range
063         *         {@code index < 0 || index >= size()}.
064         */
065        @Override
066        default T apply(final int index) {
067                return get(index);
068        }
069
070        /**
071         * @see #length()
072         * @return the size of this sequence
073         */
074        default int size() {
075                return length();
076        }
077
078        /**
079         * Tests whether a predicate holds for all elements of this sequence.
080         *
081         * @param predicate the predicate to use to test the elements.
082         * @return {@code true} if the given predicate p holds for all elements of
083         *         this sequence, {@code false} otherwise.
084         * @throws NullPointerException if the given {@code predicate} is
085         *         {@code null}.
086         */
087        default boolean forAll(final Predicate<? super T> predicate) {
088                boolean valid = true;
089
090                for (int i = 0, n = length(); i < n && valid; ++i) {
091                        valid = predicate.test(get(i));
092                }
093
094                return valid;
095        }
096
097        /**
098         * Returns a possibly parallel {@code Stream} with this sequence as its
099         * source.  It is allowable for this method to return a sequential stream.
100         *
101         * @since 3.0
102         *
103         * @return a possibly parallel {@code Stream} over the elements in this
104         * collection
105         */
106        default Stream<T> parallelStream() {
107                return StreamSupport.stream(spliterator(), true);
108        }
109
110        /**
111         * Returns {@code true} if this sequence contains the specified element.
112         *
113         * @param element element whose presence in this sequence is to be tested.
114         *        The tested element can be {@code null}.
115         * @return {@code true} if this sequence contains the specified element
116         */
117        default boolean contains(final Object element) {
118                return indexOf(element) != -1;
119        }
120
121        /**
122         * Returns the index of the first occurrence of the specified element
123         * in this sequence, or -1 if this sequence does not contain the element.
124         *
125         * @param element element to search for, can be {@code null}
126         * @return the index of the first occurrence of the specified element in
127         *          this sequence, or -1 if this sequence does not contain the element
128         */
129        default int indexOf(final Object element) {
130                return indexOf(element, 0, length());
131        }
132
133        /**
134         * Returns the index of the first occurrence of the specified element
135         * in this sequence, or -1 if this sequence does not contain the element.
136         *
137         * @param element element to search for, can be {@code null}
138         * @param start the start index (inclusively) for the element search.
139         * @return the index of the first occurrence of the specified element in
140         *          this sequence, or -1 if this sequence does not contain the element
141         * @throws IndexOutOfBoundsException for an illegal end point index value
142         *          ({@code start < 0 || start > length()}).
143         */
144        default int indexOf(final Object element, final int start) {
145                return indexOf(element, start, length());
146        }
147
148        /**
149         * Returns the index of the first occurrence of the specified element
150         * in this sequence, or -1 if this sequence does not contain the element.
151         *
152         * @param element element to search for, can be {@code null}
153         * @param start the start index (inclusively) for the element search.
154         * @param end the end index (exclusively) for the element search.
155         * @return the index of the first occurrence of the specified element in
156         *          this sequence, or -1 if this sequence does not contain the element
157         * @throws IndexOutOfBoundsException for an illegal end point index value
158         *          ({@code start < 0 || end > length() || start > end}).
159         */
160        default int indexOf(final Object element, final int start, final int end) {
161                return element != null
162                        ? indexWhere(element::equals, start, end)
163                        : indexWhere(Objects::isNull, start, end);
164        }
165
166        /**
167         * <p>
168         * Returns the index of the first element on which the given predicate
169         * returns {@code true}, or -1 if the predicate returns false for every
170         * sequence element.
171         * </p>
172         * <pre>{@code
173         * // Finding index of first null value.
174         * final int index = seq.indexOf(o -> o == null);
175         *
176         * // Assert of no null values.
177         * assert (sequence.indexOf(o -> o == null) == -1);
178         * }</pre>
179         *
180         * @param predicate the search predicate.
181         * @return the index of the first element on which the given predicate
182         *          returns {@code true}, or -1 if the predicate returns {@code false}
183         *          for every sequence element.
184         * @throws NullPointerException if the given {@code predicate} is {@code null}.
185         */
186        default int indexWhere(final Predicate<? super T> predicate) {
187                return indexWhere(predicate, 0, length());
188        }
189
190        /**
191         * <p>
192         * Returns the index of the first element on which the given predicate
193         * returns {@code true}, or -1 if the predicate returns false for every
194         * sequence element.
195         * </p>
196         * <pre>{@code
197         * // Finding index of first null value.
198         * final int index = seq.indexOf(o -> o == null);
199         *
200         * // Assert of no null values.
201         * assert (sequence.indexOf(o -> o == null) == -1);
202         * }</pre>
203         *
204         * @param predicate the search predicate.
205         * @param start the search start index
206         * @return the index of the first element on which the given predicate
207         *          returns {@code true}, or -1 if the predicate returns {@code false}
208         *          for every sequence element.
209         * @throws NullPointerException if the given {@code predicate} is {@code null}.
210         * @throws IndexOutOfBoundsException for an illegal end point index value
211         *          ({@code start < 0 || start > length()}).
212         */
213        default int indexWhere(
214                final Predicate<? super T> predicate,
215                final int start
216        ) {
217                return indexWhere(predicate, start, length());
218        }
219
220        /**
221         * <p>
222         * Returns the index of the first element on which the given predicate
223         * returns {@code true}, or -1 if the predicate returns false for every
224         * sequence element.
225         * </p>
226         * <pre>{@code
227         * // Finding index of first null value.
228         * final int index = seq.indexOf(o -> o == null);
229         *
230         * // Assert of no null values.
231         * assert (sequence.indexOf(o -> o == null) == -1);
232         * }</pre>
233         *
234         * @param predicate the search predicate.
235         * @param start the search start index
236         * @param end the search end index
237         * @return the index of the first element on which the given predicate
238         *          returns {@code true}, or -1 if the predicate returns {@code false}
239         *          for every sequence element.
240         * @throws NullPointerException if the given {@code predicate} is {@code null}.
241         * @throws IndexOutOfBoundsException for an illegal end point index value
242         *          ({@code start < 0 || end > length() || start > end}).
243         */
244        default int indexWhere(
245                final Predicate<? super T> predicate,
246                final int start,
247                final int end
248        ) {
249                requireNonNull(predicate, "Predicate");
250                checkIndex(start, end, length());
251
252                int index = -1;
253                for (int i = start; i < end && index == -1; ++i) {
254                        if (predicate.test(get(i))) {
255                                index = i;
256                        }
257                }
258                return index;
259        }
260
261        /**
262         * Returns the index of the last occurrence of the specified element
263         * in this sequence, or -1 if this sequence does not contain the element.
264         *
265         * @param element element to search for, can be {@code null}
266         * @return the index of the last occurrence of the specified element in
267         *         this sequence, or -1 if this sequence does not contain the element
268         */
269        default int lastIndexOf(final Object element) {
270                return lastIndexOf(element, 0, length());
271        }
272
273        /**
274         * Returns the index of the last occurrence of the specified element
275         * in this sequence, or -1 if this sequence does not contain the element.
276         *
277         * @param element element to search for, can be {@code null}
278         * @param end the search end index
279         * @return the index of the last occurrence of the specified element in
280         *         this sequence, or -1 if this sequence does not contain the element
281         * @throws IndexOutOfBoundsException for an illegal end point index value
282         *          ({@code end < 0 || end > length()}).
283         */
284        default int lastIndexOf(final Object element, final int end) {
285                return lastIndexOf(element, 0, end);
286        }
287
288        /**
289         * Returns the index of the last occurrence of the specified element
290         * in this sequence, or -1 if this sequence does not contain the element.
291         *
292         * @param element element to search for, can be {@code null}
293         * @param start the search start index
294         * @param end the search end index
295         * @return the index of the last occurrence of the specified element in
296         *         this sequence, or -1 if this sequence does not contain the element
297         * @throws IndexOutOfBoundsException for an illegal end point index value
298         *          ({@code start < 0 || end > length() || start > end}).
299         */
300        default int lastIndexOf(
301                final Object element,
302                final int start,
303                final int end
304        ) {
305                return element != null
306                        ? lastIndexWhere(element::equals, start, end)
307                        : lastIndexWhere(Objects::isNull, start, end);
308        }
309
310        /**
311         * Returns the index of the last element on which the given predicate
312         * returns {@code true}, or -1 if the predicate returns false for every
313         * sequence element.
314         *
315         * @param predicate the search predicate.
316         * @return the index of the last element on which the given predicate
317         *          returns {@code true}, or -1 if the predicate returns false for
318         *          every sequence element.
319         * @throws NullPointerException if the given {@code predicate} is {@code null}.
320         */
321        default int lastIndexWhere(final Predicate<? super T> predicate) {
322                return lastIndexWhere(predicate, 0, length());
323        }
324
325        /**
326         * Returns the index of the last element on which the given predicate
327         * returns {@code true}, or -1 if the predicate returns false for every
328         * sequence element.
329         *
330         * @param predicate the search predicate.
331         * @param end the search end index
332         * @return the index of the last element on which the given predicate
333         *          returns {@code true}, or -1 if the predicate returns false for
334         *          every sequence element.
335         * @throws NullPointerException if the given {@code predicate} is {@code null}.
336         * @throws IndexOutOfBoundsException for an illegal end point index value
337         *          ({@code end < 0 || end > length()}).
338         */
339        default int lastIndexWhere(
340                final Predicate<? super T> predicate,
341                final int end
342        ) {
343                return lastIndexWhere(predicate, 0, end);
344        }
345
346        /**
347         * Returns the index of the last element on which the given predicate
348         * returns {@code true}, or -1 if the predicate returns false for every
349         * sequence element.
350         *
351         * @param predicate the search predicate.
352         * @param start the search start index
353         * @param end the search end index
354         * @return the index of the last element on which the given predicate
355         *          returns {@code true}, or -1 if the predicate returns false for
356         *          every sequence element.
357         * @throws NullPointerException if the given {@code predicate} is {@code null}.
358         * @throws IndexOutOfBoundsException for an illegal end point index value
359         *          ({@code start < 0 || end > length() || start > end}).
360         */
361        default int lastIndexWhere(
362                final Predicate<? super T> predicate,
363                final int start,
364                final int end
365        ) {
366                requireNonNull(predicate, "Predicate");
367                checkIndex(start, end, length());
368
369                int index = -1;
370                for (int i = end; --i >= start && index == -1;) {
371                        if (predicate.test(get(i))) {
372                                index = i;
373                        }
374                }
375                return index;
376        }
377
378        /**
379         * Builds a new sequence by applying a function to all elements of this
380         * sequence.
381         *
382         * @param <B> the element type of the returned collection.
383         * @param mapper the function to apply to each element.
384         * @return a new sequence of type That resulting from applying the given
385         *         function f to each element of this sequence and collecting the
386         *         results.
387         * @throws NullPointerException if the element {@code mapper} is
388         *         {@code null}.
389         */
390        <B> Seq<B> map(final Function<? super T, ? extends B> mapper);
391
392        /**
393         * Return a <i>new</i> {@code Seq} with the given {@code values} appended.
394         *
395         * @since 3.4
396         *
397         * @param values the values to append
398         * @return a <i>new</i> {@code Seq} with the elements of {@code this}
399         *        sequence and the given {@code values} appended.
400         * @throws NullPointerException if the given {@code values} array is
401         *         {@code null}
402         */
403        @SuppressWarnings("unchecked")
404        default Seq<T> append(final T... values) {
405                return append(Seq.of(values));
406        }
407
408        /**
409         * Return a <i>new</i> {@code Seq} with the given {@code values} appended.
410         *
411         * @since 3.4
412         *
413         * @param values the values to append
414         * @return a <i>new</i> {@code Seq} with the elements of {@code this}
415         *        sequence and the given {@code values} appended.
416         * @throws NullPointerException if the given {@code values} iterable is
417         *         {@code null}
418         */
419        Seq<T> append(final Iterable<? extends T> values);
420
421        /**
422         * Return a <i>new</i> {@code Seq} with the given {@code values} prepended.
423         *
424         * @since 3.4
425         *
426         * @param values the values to append
427         * @return a <i>new</i> {@code Seq} with the elements of {@code this}
428         *        sequence and the given {@code values} prepended.
429         * @throws NullPointerException if the given {@code values} array is
430         *         {@code null}
431         */
432        @SuppressWarnings("unchecked")
433        default Seq<T> prepend(final T... values) {
434                return prepend(Seq.of(values));
435        }
436
437        /**
438         * Return a <i>new</i> {@code Seq} with the given {@code values} prepended.
439         *
440         * @since 3.4
441         *
442         * @param values the values to append
443         * @return a <i>new</i> {@code Seq} with the elements of {@code this}
444         *        sequence and the given {@code values} prepended.
445         * @throws NullPointerException if the given {@code values} array is
446         *         {@code null}
447         */
448        Seq<T> prepend(final Iterable<? extends T> values);
449
450        /**
451         * Returns a fixed-size list backed by the specified sequence. (Changes to
452         * the returned list "write through" to the array.) The returned list is
453         * fixed size, serializable and implements {@link RandomAccess}.
454         *
455         * @return a list view of this sequence
456         */
457        default List<T> asList() {
458                return new BaseSeqList<>(this);
459        }
460
461        /**
462         * Return an array containing all of the elements in this sequence in right
463         * order. The returned array will be "safe" in that no references to it
464         * are maintained by this sequence. (In other words, this method must allocate
465         * a new array.) The caller is thus free to modify the returned array.
466         *
467         * @see java.util.Collection#toArray()
468         *
469         * @return an array containing all of the elements in this list in right
470         *          order
471         */
472        default Object[] toArray() {
473                final Object[] array = new Object[size()];
474                for (int i = size(); --i >= 0;) {
475                        array[i] = get(i);
476                }
477                return array;
478        }
479
480        /**
481         * Return an array containing all of the elements in this sequence in right
482         * order; the runtime type of the returned array is that of the specified
483         * array. If this sequence fits in the specified array, it is returned
484         * therein. Otherwise, a new array is allocated with the runtime type of the
485         * specified array and the length of this array.
486         * <p>
487         * If this sequence fits in the specified array with room to spare (i.e.,
488         * the array has more elements than this array), the element in the array
489         * immediately following the end of this array is set to null. (This is
490         * useful in determining the length of the array only if the caller knows
491         * that the list does not contain any null elements.)
492         *
493         * @see java.util.Collection#toArray(Object[])
494         *
495         * @param <B> the runtime type of the array to contain the sequence
496         * @param array the array into which the elements of this array are to be
497         *         stored, if it is big enough; otherwise, a new array of the same
498         *         runtime type is allocated for this purpose.
499         * @return an array containing the elements of this array
500         * @throws ArrayStoreException if the runtime type of the specified array is
501         *         not a super type of the runtime type of every element in this
502         *         array
503         * @throws NullPointerException if the given {@code array} is {@code null}.
504         */
505        @SuppressWarnings("unchecked")
506        default <B> B[] toArray(final B[] array) {
507                if (array.length < length()) {
508                        final Object[] copy = (Object[])java.lang.reflect.Array
509                                .newInstance(array.getClass().getComponentType(), length());
510
511                        for (int i = length(); --i >= 0;) {
512                                copy[i] = get(i);
513                        }
514
515                        return (B[])copy;
516                }
517
518                for (int i = 0, n = length(); i < n; ++i) {
519                        ((Object[])array)[i] = get(i);
520                }
521                if (array.length > length()) {
522                        array[length()] = null;
523                }
524
525                return array;
526        }
527
528        /**
529         * Returns an array containing the elements of this sequence, using the
530         * provided generator function to allocate the returned array.
531         *
532         * @since 4.4
533         *
534         * @param generator a function which produces a new array of the desired
535         *        type and the provided length
536         * @param <B> the element type of the resulting array
537         * @return an array containing the elements in {@code this} sequence
538         * @throws ArrayStoreException if the runtime type of the specified array is
539         *         not a super type of the runtime type of every element in this
540         *         array
541         * @throws NullPointerException if the given {@code generator} is {@code null}.
542         */
543        default <B> B[] toArray(final IntFunction<B[]> generator) {
544                return toArray(generator.apply(length()));
545        }
546
547        /**
548         * Returns a view of the portion of this sequence between the specified
549         * {@code start}, inclusive, and {@code end}, exclusive. (If {@code start}
550         * and {@code end} are equal, the returned sequence has the length zero.)
551         * The returned sequence is backed by this sequence, so non-structural
552         * changes in the returned sequence are reflected in this sequence, and
553         * vice-versa.
554         * <p>
555         * This method eliminates the need for explicit range operations (of the
556         * populationSort that commonly exist for arrays). Any operation that
557         * expects an sequence can be used as a range operation by passing an sub
558         * sequence view instead of an whole sequence.
559         *
560         * @param start lower end point (inclusive) of the sub array.
561         * @return a view of the specified range within this array.
562         * @throws IndexOutOfBoundsException for an illegal end point index value
563         *          ({@code start < 0 || start > length()}).
564         */
565        Seq<T> subSeq(final int start);
566
567        /**
568         * Returns a view of the portion of this sequence between the specified
569         * {@code start}, inclusive, and {@code end}, exclusive. (If {@code start}
570         * and {@code end} are equal, the returned sequence has the length zero.)
571         * The returned sequence is backed by this sequence, so non-structural
572         * changes in the returned sequence are reflected in this array, and
573         * vice-versa.
574         * <p>
575         * This method eliminates the need for explicit range operations (of the
576         * populationSort that commonly exist for arrays). Any operation that
577         * expects an array can be used as a range operation by passing an sub
578         * sequence view instead of an whole sequence.
579         *
580         * @param start low end point (inclusive) of the sub sequence.
581         * @param end high end point (exclusive) of the sub sequence.
582         * @return a view of the specified range within this sequence.
583         * @throws IndexOutOfBoundsException for an illegal end point index value
584         *          ({@code start < 0 || end > length() || start > end}).
585         */
586        Seq<T> subSeq(final int start, final int end);
587
588        /**
589         * Test whether the given array is sorted in ascending order.
590         *
591         * @return {@code true} if the given {@code array} is sorted in ascending
592         *         order, {@code false} otherwise.
593         * @throws NullPointerException if the given array or one of it's element is
594         *         {@code null}.
595         */
596        @SuppressWarnings("unchecked")
597        default boolean isSorted() {
598                boolean sorted = true;
599                for (int i = 0, n = length() - 1; i < n && sorted; ++i) {
600                        sorted = ((Comparable<T>)get(i)).compareTo(get(i + 1)) <= 0;
601                }
602
603                return sorted;
604        }
605
606        /**
607         * Test whether the given array is sorted in ascending order. The order of
608         * the array elements is defined by the given comparator.
609         *
610         * @param comparator the comparator which defines the order.
611         * @return {@code true} if the given {@code array} is sorted in ascending
612         *         order, {@code false} otherwise.
613         * @throws NullPointerException if the given array or one of it's element or
614         *         the comparator is {@code null}.
615         */
616        default boolean isSorted(final Comparator<? super T> comparator) {
617                boolean sorted = true;
618                for (int i = 0, n = length() - 1; i < n && sorted; ++i) {
619                        sorted = comparator.compare(get(i), get(i + 1)) <= 0;
620                }
621
622                return sorted;
623        }
624
625        /**
626         * Return this sequence as {@code MSeq} instance. If {@code this} is not a
627         * {@code MSeq} a new seq is created.
628         *
629         * @since 3.8
630         *
631         * @return a {@code MSeq} with this values
632         */
633        default MSeq<T> asMSeq() {
634                return this instanceof MSeq ? (MSeq<T>)this : MSeq.of(this);
635        }
636
637        /**
638         * Return this sequence as {@code ISeq} instance. If {@code this} is not a
639         * {@code ISeq} a new seq is created.
640         *
641         * @since 3.8
642         *
643         * @return a {@code ISeq} with this values
644         */
645        default ISeq<T> asISeq() {
646                return this instanceof ISeq ? (ISeq<T>)this : ISeq.of(this);
647        }
648
649        /**
650         * Returns the hash code value for this sequence. The hash code is defined
651         * as followed:
652         *
653         * <pre>{@code
654         * int hashCode = 1;
655         * final Iterator<E> it = seq.iterator();
656         * while (it.hasNext()) {
657         *     final E obj = it.next();
658         *     hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
659         * }
660         * }</pre>
661         *
662         * @see List#hashCode()
663         * @see Seq#hashCode(BaseSeq)
664         *
665         * @return the hash code value for this list
666         */
667        @Override
668        int hashCode();
669
670        /**
671         * Compares the specified object with this sequence for equality. Returns
672         * true if and only if the specified object is also a sequence, both
673         * sequence have the same size, and all corresponding pairs of elements in
674         * the two sequences are equal. (Two elements e1 and e2 are equal if
675         * (e1==null ? e2==null : e1.equals(e2)).) This definition ensures that the
676         * equals method works properly across different implementations of the Seq
677         * interface.
678         *
679         * @see List#equals(Object)
680         * @see Seq#equals(BaseSeq, Object)
681         *
682         * @param object the object to be compared for equality with this sequence.
683         * @return {@code true} if the specified object is equal to this sequence,
684         *          {@code false} otherwise.
685         */
686        @Override
687        boolean equals(final Object object);
688
689        /**
690         * Create a string representation of the given sequence.
691         *
692         * @param prefix the prefix of the string representation; e.g {@code '['}.
693         * @param separator the separator of the array elements; e.g. {@code ','}.
694         * @param suffix the suffix of the string representation; e.g. {@code ']'}.
695         * @return the string representation of this sequence.
696         */
697        default String toString(
698                final String prefix,
699                final String separator,
700                final String suffix
701        ) {
702                return stream()
703                        .map(Objects::toString)
704                        .collect(joining(separator, prefix, suffix));
705        }
706
707        /**
708         * Create a string representation of the given sequence.
709         *
710         * @param separator the separator of the array elements; e.g. {@code ','}.
711         * @return the string representation of this sequence.
712         */
713        default String toString(final String separator) {
714                return toString("", separator, "");
715        }
716
717        /**
718         * Unified method for calculating the hash code of every {@link Seq}
719         * implementation. The hash code is defined as followed:
720         *
721         * <pre>{@code
722         * int hashCode = 1;
723         * final Iterator<E> it = seq.iterator();
724         * while (it.hasNext()) {
725         *     final E obj = it.next();
726         *     hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
727         * }
728         * }</pre>
729         *
730         * @see Seq#hashCode()
731         * @see List#hashCode()
732         *
733         * @param seq the sequence to calculate the hash code for.
734         * @return the hash code of the given sequence.
735         */
736        static int hashCode(final BaseSeq<?> seq) {
737                int hash = 1;
738                for (Object element : seq) {
739                        hash = 31*hash + (element == null ? 0: element.hashCode());
740                }
741                return hash;
742        }
743
744        /**
745         * Unified method for compare to sequences for equality.
746         *
747         * @see Seq#equals(Object)
748         *
749         * @param seq the sequence to test for equality.
750         * @param obj the object to test for equality with the sequence.
751         * @return {@code true} if the given objects are sequences and contain the
752         *          same objects in the same order, {@code false} otherwise.
753         */
754        static boolean equals(final BaseSeq<?> seq, final Object obj) {
755                if (obj == seq) {
756                        return true;
757                }
758                if (!(obj instanceof final Seq<?> other)) {
759                        return false;
760                }
761
762                boolean equals = seq.length() == other.length();
763                for (int i = seq.length(); equals && --i >= 0;) {
764                        final Object element = seq.get(i);
765                        equals = element != null
766                                ? element.equals(other.get(i))
767                                : other.get(i) == null;
768                }
769                return equals;
770        }
771
772        /* *************************************************************************
773         *  Some static helper methods.
774         * ************************************************************************/
775
776        /**
777         * Return a sequence whose elements are all the elements of the first
778         * element followed by all the elements of the sequence.
779         *
780         * @since 5.0
781         *
782         * @param a the first element
783         * @param b the appending sequence
784         * @param <T> the type of the sequence elements
785         * @return the concatenation of the two inputs
786         * @throws NullPointerException if one of the second arguments is
787         *         {@code null}
788         */
789        @SuppressWarnings("unchecked")
790        static <T> Seq<T> concat(
791                final T a,
792                final Seq<? extends T> b
793        ) {
794                return ((Seq<T>)b).prepend(a);
795        }
796
797        /**
798         * Return a sequence whose elements are all the elements of the first
799         * sequence followed by all the elements of the vararg array.
800         *
801         * @since 5.0
802         *
803         * @param a the first sequence
804         * @param b the vararg elements
805         * @param <T> the type of the sequence elements
806         * @return the concatenation of the two inputs
807         * @throws NullPointerException if one of the arguments is {@code null}
808         */
809        @SuppressWarnings("unchecked")
810        static <T> Seq<T> concat(
811                final Seq<? extends T> a,
812                final T... b
813        ) {
814                return ((Seq<T>)a).append(b);
815        }
816
817        /**
818         * Return a sequence whose elements are all the elements of the first
819         * sequence followed by all the elements of the second sequence.
820         *
821         * @since 5.0
822         *
823         * @param a the first sequence
824         * @param b the second sequence
825         * @param <T> the type of the sequence elements
826         * @return the concatenation of the two input sequences
827         * @throws NullPointerException if one of the arguments is {@code null}
828         */
829        @SuppressWarnings("unchecked")
830        static <T> Seq<T> concat(
831                final Seq<? extends T> a,
832                final Seq<? extends T> b
833        ) {
834                return ((Seq<T>)a).append(b);
835        }
836
837        /* *************************************************************************
838         *  Some static factory methods.
839         * ************************************************************************/
840
841        /**
842         * Single instance of an empty {@code Seq}.
843         *
844         * @since 3.3
845         */
846        Seq<?> EMPTY = ISeq.EMPTY;
847
848        /**
849         * Return an empty {@code Seq}.
850         *
851         * @since 3.3
852         *
853         * @param <T> the element type of the returned {@code Seq}.
854         * @return an empty {@code Seq}.
855         */
856        static <T> Seq<T> empty() {
857                return ISeq.empty();
858        }
859
860        /**
861         * Returns a {@code Collector} that accumulates the input elements into a
862         * new {@code Seq}.
863         *
864         * @param <T> the type of the input elements
865         * @return a {@code Collector} which collects all the input elements into a
866         *         {@code Seq}, in encounter order
867         */
868        static <T> Collector<T, ?, Seq<T>> toSeq() {
869                return Collector.of(
870                        (Supplier<List<T>>)ArrayList::new,
871                        List::add,
872                        (left, right) -> { left.addAll(right); return left; },
873                        Seq::of
874                );
875        }
876
877        /**
878         * Returns a {@code Collector} that accumulates the last {@code n} input
879         * elements into a new {@code Seq}.
880         *
881         * @since 5.0
882         *
883         * @param maxSize the maximal size of the collected sequence
884         * @param <T> the type of the input elements
885         * @return a {@code Collector} which collects maximal {@code maxSize} of the
886         *         input elements into an {@code ISeq}, in encounter order
887         * @throws IllegalArgumentException if the {@code maxSize} is negative
888         */
889        static <T> Collector<T, ?, Seq<T>> toSeq(final int maxSize) {
890                return Seqs.toSeq(maxSize, Buffer::toSeq);
891        }
892
893        /**
894         * Create a new {@code Seq} from the given values.
895         *
896         * @param <T> the element type
897         * @param values the array values.
898         * @return a new {@code Seq} with the given values.
899         * @throws NullPointerException if the {@code values} array is {@code null}.
900         */
901        @SafeVarargs
902        static <T> Seq<T> of(final T... values) {
903                return ISeq.of(values);
904        }
905
906        /**
907         * Create a new {@code Seq} from the given values.
908         *
909         * @param <T> the element type
910         * @param values the array values.
911         * @return a new {@code Seq} with the given values.
912         * @throws NullPointerException if the {@code values} array is {@code null}.
913         */
914        static <T> Seq<T> of(final Iterable<? extends T> values) {
915                return ISeq.of(values);
916        }
917
918        /**
919         * Creates a new sequence, which is filled with objects created be the given
920         * {@code supplier}.
921         *
922         * @since 3.3
923         *
924         * @param <T> the element type of the sequence
925         * @param supplier the {@code Supplier} which creates the elements, the
926         *        returned sequence is filled with
927         * @param length the length of the returned sequence
928         * @return a new sequence filled with elements given by the {@code supplier}
929         * @throws NegativeArraySizeException if the given {@code length} is
930         *         negative
931         * @throws NullPointerException if the given {@code supplier} is
932         *         {@code null}
933         */
934        static <T> Seq<T> of(Supplier<? extends T> supplier, final int length) {
935                return ISeq.of(supplier, length);
936        }
937
938        /**
939         * Returns a sequence backed by the specified {@code seq}. (Changes to the
940         * given sequence (if writeable) are "write through" to the returned
941         * sequence.)  This method acts as bridge between basic sequences and
942         * sequence-based APIs.
943         *
944         * @since 6.0
945         *
946         * @param seq the basic sequence containing the elements
947         * @param <T> the element type
948         * @return a sequence view of the given {@code seq}
949         * @throws NullPointerException if the given list is {@code null}
950         */
951        static <T> Seq<T> viewOf(final BaseSeq<? extends T> seq) {
952                return seq.isEmpty()
953                        ? empty()
954                        : new SeqView<>(new BaseSeqList<>(seq));
955        }
956
957        /**
958         * Returns a sequence backed by the specified list. (Changes to the given
959         * list are "write through" to the returned sequence.)  This method acts
960         * as bridge between collection-based and sequence-based APIs.
961         *
962         * @since 4.2
963         *
964         * @param list the list containing the elements
965         * @param <T> the element type
966         * @return a sequence view of the given {@code list}
967         * @throws NullPointerException if the given list is {@code null}
968         */
969        static <T> Seq<T> viewOf(final List<? extends T> list) {
970                return list.isEmpty()
971                        ? empty()
972                        : new SeqView<>(list);
973        }
974
975        /**
976         * Returns a fixed-size sequence backed by the specified array. (Changes to
977         * the given array are "write through" to the returned sequence.)  This
978         * method acts as bridge between array-based and sequence-based APIs.
979         *
980         * @since 4.2
981         *
982         * @param array the array containing the sequence elements
983         * @param <T> the element type
984         * @return a sequence view of the given {@code array}
985         * @throws NullPointerException if the given array is {@code null}
986         */
987        static <T> Seq<T> viewOf(final T[] array) {
988                return array.length == 0
989                        ? empty()
990                        : new SeqView<>(Arrays.asList(array));
991        }
992
993}