001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 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="https://download.java.net/java/early_access/jdk21/docs/api/java.base/java/util/Collection.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 * {@snippet lang="java": 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 * } 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 * {@snippet lang="java": 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 * } 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 * {@snippet lang="java": 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 * } 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 the 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 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 a sequence can be used as a range operation by passing a 558 * subsequence view instead of a whole sequence. 559 * 560 * @param start lower end point (inclusive) of the subarray. 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 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 a 578 * subsequence view instead of a whole sequence. 579 * 580 * @param start low-end point (inclusive) of the subsequence. 581 * @param end high-end point (exclusive) of the subsequence. 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 its 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 its elements 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 * {@snippet lang="java": 653 * int hashCode = 1; 654 * final Iterator<E> it = seq.iterator(); 655 * while (it.hasNext()) { 656 * final E obj = it.next(); 657 * hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode()); 658 * } 659 * } 660 * 661 * @see List#hashCode() 662 * @see Seq#hashCode(BaseSeq) 663 * 664 * @return the hash code value for this list 665 */ 666 @Override 667 int hashCode(); 668 669 /** 670 * Compares the specified object with this sequence for equality. Returns 671 * true if and only if the specified object is also a sequence, both 672 * sequences have the same size, and all corresponding pairs of elements in 673 * the two sequences are equal. (Two elements e1 and e2 are equal if 674 * (e1==null ? e2==null : e1.equals(e2)).) This definition ensures that the 675 * equals method works properly across different implementations of the Seq 676 * interface. 677 * 678 * @see List#equals(Object) 679 * @see Seq#equals(BaseSeq, Object) 680 * 681 * @param object the object to be compared for equality with this sequence. 682 * @return {@code true} if the specified object is equal to this sequence, 683 * {@code false} otherwise. 684 */ 685 @Override 686 boolean equals(final Object object); 687 688 /** 689 * Create a string representation of the given sequence. 690 * 691 * @param prefix the prefix of the string representation; e.g {@code '['}. 692 * @param separator the separator of the array elements; e.g. {@code ','}. 693 * @param suffix the suffix of the string representation; e.g. {@code ']'}. 694 * @return the string representation of this sequence. 695 */ 696 default String toString( 697 final String prefix, 698 final String separator, 699 final String suffix 700 ) { 701 return stream() 702 .map(Objects::toString) 703 .collect(joining(separator, prefix, suffix)); 704 } 705 706 /** 707 * Create a string representation of the given sequence. 708 * 709 * @param separator the separator of the array elements; e.g. {@code ','}. 710 * @return the string representation of this sequence. 711 */ 712 default String toString(final String separator) { 713 return toString("", separator, ""); 714 } 715 716 /** 717 * Unified method for calculating the hash code of every {@link Seq} 718 * implementation. The hash code is defined as followed: 719 * {@snippet lang="java": 720 * int hashCode = 1; 721 * final Iterator<E> it = seq.iterator(); 722 * while (it.hasNext()) { 723 * final E obj = it.next(); 724 * hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode()); 725 * } 726 * } 727 * 728 * @see Seq#hashCode() 729 * @see List#hashCode() 730 * 731 * @param seq the sequence to calculate the hash code for. 732 * @return the hash code of the given sequence. 733 */ 734 static int hashCode(final BaseSeq<?> seq) { 735 int hash = 1; 736 for (Object element : seq) { 737 hash = 31*hash + (element == null ? 0: element.hashCode()); 738 } 739 return hash; 740 } 741 742 /** 743 * Unified method for compare to sequences for equality. 744 * 745 * @see Seq#equals(Object) 746 * 747 * @param seq the sequence to test for equality. 748 * @param obj the object to test for equality with the sequence. 749 * @return {@code true} if the given objects are sequences and contain the 750 * same objects in the same order, {@code false} otherwise. 751 */ 752 static boolean equals(final BaseSeq<?> seq, final Object obj) { 753 if (obj == seq) { 754 return true; 755 } 756 if (!(obj instanceof final Seq<?> other)) { 757 return false; 758 } 759 760 boolean equals = seq.length() == other.length(); 761 for (int i = seq.length(); equals && --i >= 0;) { 762 final Object element = seq.get(i); 763 equals = element != null 764 ? element.equals(other.get(i)) 765 : other.get(i) == null; 766 } 767 return equals; 768 } 769 770 /* ************************************************************************* 771 * Some static helper methods. 772 * ************************************************************************/ 773 774 /** 775 * Return a sequence whose elements are all the elements of the first 776 * element followed by all the elements of the sequence. 777 * 778 * @since 5.0 779 * 780 * @param a the first element 781 * @param b the appending sequence 782 * @param <T> the type of the sequence elements 783 * @return the concatenation of the two inputs 784 * @throws NullPointerException if one of the second arguments is 785 * {@code null} 786 */ 787 @SuppressWarnings("unchecked") 788 static <T> Seq<T> concat( 789 final T a, 790 final Seq<? extends T> b 791 ) { 792 return ((Seq<T>)b).prepend(a); 793 } 794 795 /** 796 * Return a sequence whose elements are all the elements of the first 797 * sequence followed by all the elements of the vararg array. 798 * 799 * @since 5.0 800 * 801 * @param a the first sequence 802 * @param b the vararg elements 803 * @param <T> the type of the sequence elements 804 * @return the concatenation of the two inputs 805 * @throws NullPointerException if one of the arguments is {@code null} 806 */ 807 @SuppressWarnings("unchecked") 808 static <T> Seq<T> concat( 809 final Seq<? extends T> a, 810 final T... b 811 ) { 812 return ((Seq<T>)a).append(b); 813 } 814 815 /** 816 * Return a sequence whose elements are all the elements of the first 817 * sequence followed by all the elements of the second sequence. 818 * 819 * @since 5.0 820 * 821 * @param a the first sequence 822 * @param b the second sequence 823 * @param <T> the type of the sequence elements 824 * @return the concatenation of the two input sequences 825 * @throws NullPointerException if one of the arguments is {@code null} 826 */ 827 @SuppressWarnings("unchecked") 828 static <T> Seq<T> concat( 829 final Seq<? extends T> a, 830 final Seq<? extends T> b 831 ) { 832 return ((Seq<T>)a).append(b); 833 } 834 835 /* ************************************************************************* 836 * Some static factory methods. 837 * ************************************************************************/ 838 839 /** 840 * Single instance of an empty {@code Seq}. 841 * 842 * @since 3.3 843 */ 844 Seq<?> EMPTY = ISeq.EMPTY; 845 846 /** 847 * Return an empty {@code Seq}. 848 * 849 * @since 3.3 850 * 851 * @param <T> the element type of the returned {@code Seq}. 852 * @return an empty {@code Seq}. 853 */ 854 static <T> Seq<T> empty() { 855 return ISeq.empty(); 856 } 857 858 /** 859 * Returns a {@code Collector} that accumulates the input elements into a 860 * new {@code Seq}. 861 * 862 * @param <T> the type of the input elements 863 * @return a {@code Collector} which collects all the input elements into a 864 * {@code Seq}, in encounter order 865 */ 866 static <T> Collector<T, ?, Seq<T>> toSeq() { 867 return Collector.of( 868 (Supplier<List<T>>)ArrayList::new, 869 List::add, 870 (left, right) -> { left.addAll(right); return left; }, 871 Seq::of 872 ); 873 } 874 875 /** 876 * Returns a {@code Collector} that accumulates the last {@code n} input 877 * elements into a new {@code Seq}. 878 * 879 * @since 5.0 880 * 881 * @param maxSize the maximal size of the collected sequence 882 * @param <T> the type of the input elements 883 * @return a {@code Collector} which collects maximal {@code maxSize} of the 884 * input elements into an {@code ISeq}, in encounter order 885 * @throws IllegalArgumentException if the {@code maxSize} is negative 886 */ 887 static <T> Collector<T, ?, Seq<T>> toSeq(final int maxSize) { 888 return Seqs.toSeq(maxSize, Buffer::toSeq); 889 } 890 891 /** 892 * Create a new {@code Seq} from the given values. 893 * 894 * @param <T> the element type 895 * @param values the array values. 896 * @return a new {@code Seq} with the given values. 897 * @throws NullPointerException if the {@code values} array is {@code null}. 898 */ 899 @SafeVarargs 900 static <T> Seq<T> of(final T... values) { 901 return ISeq.of(values); 902 } 903 904 /** 905 * Create a new {@code Seq} from the given values. 906 * 907 * @param <T> the element type 908 * @param values the array values. 909 * @return a new {@code Seq} with the given values. 910 * @throws NullPointerException if the {@code values} array is {@code null}. 911 */ 912 static <T> Seq<T> of(final Iterable<? extends T> values) { 913 return ISeq.of(values); 914 } 915 916 /** 917 * Creates a new sequence, which is filled with objects created be the given 918 * {@code supplier}. 919 * 920 * @since 3.3 921 * 922 * @param <T> the element type of the sequence 923 * @param supplier the {@code Supplier} which creates the elements, the 924 * returned sequence is filled with 925 * @param length the length of the returned sequence 926 * @return a new sequence filled with elements given by the {@code supplier} 927 * @throws NegativeArraySizeException if the given {@code length} is 928 * negative 929 * @throws NullPointerException if the given {@code supplier} is 930 * {@code null} 931 */ 932 static <T> Seq<T> of(Supplier<? extends T> supplier, final int length) { 933 return ISeq.of(supplier, length); 934 } 935 936 /** 937 * Returns a sequence backed by the specified {@code seq}. (Changes to the 938 * given sequence (if writeable) are "write through" to the returned 939 * sequence.) This method acts as a bridge between basic sequences and 940 * sequence-based APIs. 941 * 942 * @since 6.0 943 * 944 * @param seq the basic sequence containing the elements 945 * @param <T> the element type 946 * @return a sequence view of the given {@code seq} 947 * @throws NullPointerException if the given list is {@code null} 948 */ 949 static <T> Seq<T> viewOf(final BaseSeq<? extends T> seq) { 950 return seq.isEmpty() 951 ? empty() 952 : new SeqView<>(new BaseSeqList<>(seq)); 953 } 954 955 /** 956 * Returns a sequence backed by the specified list. (Changes to the given 957 * list are "write through" to the returned sequence.) This method acts 958 * as a bridge between collection-based and sequence-based APIs. 959 * 960 * @since 4.2 961 * 962 * @param list the list containing the elements 963 * @param <T> the element type 964 * @return a sequence view of the given {@code list} 965 * @throws NullPointerException if the given list is {@code null} 966 */ 967 static <T> Seq<T> viewOf(final List<? extends T> list) { 968 return list.isEmpty() 969 ? empty() 970 : new SeqView<>(list); 971 } 972 973 /** 974 * Returns a fixed-size sequence backed by the specified array. (Changes to 975 * the given array are "write through" to the returned sequence.) This 976 * method acts as a bridge between array-based and sequence-based APIs. 977 * 978 * @since 4.2 979 * 980 * @param array the array containing the sequence elements 981 * @param <T> the element type 982 * @return a sequence view of the given {@code array} 983 * @throws NullPointerException if the given array is {@code null} 984 */ 985 static <T> Seq<T> viewOf(final T[] array) { 986 return array.length == 0 987 ? empty() 988 : new SeqView<>(Arrays.asList(array)); 989 } 990 991}