Seq.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-6.2.0).
003  * Copyright (c) 2007-2021 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  */
020 package io.jenetics.util;
021 
022 import static java.util.Objects.requireNonNull;
023 import static java.util.stream.Collectors.joining;
024 import static io.jenetics.internal.collection.Array.checkIndex;
025 
026 import java.util.ArrayList;
027 import java.util.Arrays;
028 import java.util.Comparator;
029 import java.util.List;
030 import java.util.Objects;
031 import java.util.RandomAccess;
032 import java.util.function.Function;
033 import java.util.function.IntFunction;
034 import java.util.function.Predicate;
035 import java.util.function.Supplier;
036 import java.util.stream.Collector;
037 import java.util.stream.Stream;
038 import 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  */
051 public 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 <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 <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 <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 <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 low 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 Seq)) {
759             return false;
760         }
761 
762         final Seq<?> other = (Seq<?>)obj;
763         boolean equals = seq.length() == other.length();
764         for (int i = seq.length(); equals && --i >= 0;) {
765             final Object element = seq.get(i);
766             equals = element != null
767                 ? element.equals(other.get(i))
768                 : other.get(i== null;
769         }
770         return equals;
771     }
772 
773     /* *************************************************************************
774      *  Some static helper methods.
775      * ************************************************************************/
776 
777     /**
778      * Return a sequence whose elements are all the elements of the first
779      * element followed by all the elements of the sequence.
780      *
781      @since 5.0
782      *
783      @param a the first element
784      @param b the appending sequence
785      @param <T> the type of the sequence elements
786      @return the concatenation of the two inputs
787      @throws NullPointerException if one of the second arguments is
788      *         {@code null}
789      */
790     @SuppressWarnings("unchecked")
791     static <T> Seq<T> concat(
792         final T a,
793         final Seq<? extends T> b
794     ) {
795         return ((Seq<T>)b).prepend(a);
796     }
797 
798     /**
799      * Return a sequence whose elements are all the elements of the first
800      * sequence followed by all the elements of the vararg array.
801      *
802      @since 5.0
803      *
804      @param a the first sequence
805      @param b the vararg elements
806      @param <T> the type of the sequence elements
807      @return the concatenation of the two inputs
808      @throws NullPointerException if one of the arguments is {@code null}
809      */
810     @SuppressWarnings("unchecked")
811     static <T> Seq<T> concat(
812         final Seq<? extends T> a,
813         final T... b
814     ) {
815         return ((Seq<T>)a).append(b);
816     }
817 
818     /**
819      * Return a sequence whose elements are all the elements of the first
820      * sequence followed by all the elements of the second sequence.
821      *
822      @since 5.0
823      *
824      @param a the first sequence
825      @param b the second sequence
826      @param <T> the type of the sequence elements
827      @return the concatenation of the two input sequences
828      @throws NullPointerException if one of the arguments is {@code null}
829      */
830     @SuppressWarnings("unchecked")
831     static <T> Seq<T> concat(
832         final Seq<? extends T> a,
833         final Seq<? extends T> b
834     ) {
835         return ((Seq<T>)a).append(b);
836     }
837 
838     /* *************************************************************************
839      *  Some static factory methods.
840      * ************************************************************************/
841 
842     /**
843      * Single instance of an empty {@code Seq}.
844      *
845      @since 3.3
846      */
847     Seq<?> EMPTY = ISeq.EMPTY;
848 
849     /**
850      * Return an empty {@code Seq}.
851      *
852      @since 3.3
853      *
854      @param <T> the element type of the returned {@code Seq}.
855      @return an empty {@code Seq}.
856      */
857     static <T> Seq<T> empty() {
858         return ISeq.empty();
859     }
860 
861     /**
862      * Returns a {@code Collector} that accumulates the input elements into a
863      * new {@code Seq}.
864      *
865      @param <T> the type of the input elements
866      @return a {@code Collector} which collects all the input elements into a
867      *         {@code Seq}, in encounter order
868      */
869     static <T> Collector<T, ?, Seq<T>> toSeq() {
870         return Collector.of(
871             (Supplier<List<T>>)ArrayList::new,
872             List::add,
873             (left, right-> left.addAll(right)return left; },
874             Seq::of
875         );
876     }
877 
878     /**
879      * Returns a {@code Collector} that accumulates the last {@code n} input
880      * elements into a new {@code Seq}.
881      *
882      @since 5.0
883      *
884      @param maxSize the maximal size of the collected sequence
885      @param <T> the type of the input elements
886      @return a {@code Collector} which collects maximal {@code maxSize} of the
887      *         input elements into an {@code ISeq}, in encounter order
888      @throws IllegalArgumentException if the {@code maxSize} is negative
889      */
890     static <T> Collector<T, ?, Seq<T>> toSeq(final int maxSize) {
891         return Seqs.toSeq(maxSize, Buffer::toSeq);
892     }
893 
894     /**
895      * Create a new {@code Seq} from the given values.
896      *
897      @param <T> the element type
898      @param values the array values.
899      @return a new {@code Seq} with the given values.
900      @throws NullPointerException if the {@code values} array is {@code null}.
901      */
902     @SafeVarargs
903     static <T> Seq<T> of(final T... values) {
904         return ISeq.of(values);
905     }
906 
907     /**
908      * Create a new {@code Seq} from the given values.
909      *
910      @param <T> the element type
911      @param values the array values.
912      @return a new {@code Seq} with the given values.
913      @throws NullPointerException if the {@code values} array is {@code null}.
914      */
915     static <T> Seq<T> of(final Iterable<? extends T> values) {
916         return ISeq.of(values);
917     }
918 
919     /**
920      * Creates a new sequence, which is filled with objects created be the given
921      * {@code supplier}.
922      *
923      @since 3.3
924      *
925      @param <T> the element type of the sequence
926      @param supplier the {@code Supplier} which creates the elements, the
927      *        returned sequence is filled with
928      @param length the length of the returned sequence
929      @return a new sequence filled with elements given by the {@code supplier}
930      @throws NegativeArraySizeException if the given {@code length} is
931      *         negative
932      @throws NullPointerException if the given {@code supplier} is
933      *         {@code null}
934      */
935     static <T> Seq<T> of(Supplier<? extends T> supplier, final int length) {
936         return ISeq.of(supplier, length);
937     }
938 
939     /**
940      * Returns a sequence backed by the specified {@code seq}. (Changes to the
941      * given sequence (if writeable) are "write through" to the returned
942      * sequence.)  This method acts as bridge between basic sequences and
943      * sequence-based APIs.
944      *
945      @since 6.0
946      *
947      @param seq the basic sequence containing the elements
948      @param <T> the element type
949      @return a sequence view of the given {@code seq}
950      @throws NullPointerException if the given list is {@code null}
951      */
952     static <T> Seq<T> viewOf(final BaseSeq<? extends T> seq) {
953         return seq.isEmpty()
954             ? empty()
955             new SeqView<>(new BaseSeqList<>(seq));
956     }
957 
958     /**
959      * Returns a sequence backed by the specified list. (Changes to the given
960      * list are "write through" to the returned sequence.)  This method acts
961      * as bridge between collection-based and sequence-based APIs.
962      *
963      @since 4.2
964      *
965      @param list the list containing the elements
966      @param <T> the element type
967      @return a sequence view of the given {@code list}
968      @throws NullPointerException if the given list is {@code null}
969      */
970     static <T> Seq<T> viewOf(final List<? extends T> list) {
971         return list.isEmpty()
972             ? empty()
973             new SeqView<>(list);
974     }
975 
976     /**
977      * Returns a fixed-size sequence backed by the specified array. (Changes to
978      * the given array are "write through" to the returned sequence.)  This
979      * method acts as bridge between array-based and sequence-based APIs.
980      *
981      @since 4.2
982      *
983      @param array the array containing the sequence elements
984      @param <T> the element type
985      @return a sequence view of the given {@code array}
986      @throws NullPointerException if the given array is {@code null}
987      */
988     static <T> Seq<T> viewOf(final T[] array) {
989         return array.length == 0
990             ? empty()
991             new SeqView<>(Arrays.asList(array));
992     }
993 
994 }