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