All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ix.Ix Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
/*
 * Copyright 2011-2016 David Karnok
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ix;

import java.util.*;
import java.util.concurrent.Callable;

/**
 * Base class and entry point for fluent Iterables.
 * 

* All operators tolerate {@code null} elements. *

* The Iterables have to be run in a single-threaded manner and none of * the participating operators expect or support concurrency. * @param the value type * @since 1.0 */ public abstract class Ix implements Iterable { /** * Emits all characters from the given CharSequence as integer values. *

* The result's iterator() doesn't support remove(). * @param cs the source character sequence, not null * @return the new Ix instance * @throws NullPointerException if cs is null * @since 1.0 */ public static Ix characters(CharSequence cs) { return new IxCharacters(cs, 0, cs.length()); } /** * Emits a range of characters from the given CharSequence as integer values. *

* The result's iterator() doesn't support remove(). * @param cs the source character sequence, not null * @param start the start character index, inclusive, non-negative * @param end the end character index, exclusive, non-negative * @return the new Ix instance * @throws NullPointerException if cs is null * @throws IndexOutOfBoundsException if start is out of range [0, cs.length] * @since 1.0 */ public static Ix characters(CharSequence cs, int start, int end) { int len = cs.length(); if (start < 0 || end < 0 || start > len || end > len) { throw new IndexOutOfBoundsException("start=" + start + ", end=" + end + ", length=" + len); } return new IxCharacters(cs, start, end); } /** * Concatenates the elements of Iterable sources, provided as an Iterable itself, sequentially. *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the common base type * @param sources the Iterable sequence of source Iterables * @return the new Ix instance * @throws NullPointerException if sources is null * @since 1.0 * @see #merge(Iterable) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public static Ix concat(Iterable> sources) { return new IxFlattenIterable, T>( (Iterable)nullCheck(sources, "sources is null"), IdentityHelper.>instance()); } /** * Concatenates the elements of two Iterable sources sequentially *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the value type * @param source1 the first source, not null * @param source2 the second source, not null * @return the new Iterable source * @throws NullPointerException if any of the sources is null * @since 1.0 */ @SuppressWarnings("unchecked") public static Ix concat(Iterable source1, Iterable source2) { return concatArray(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null")); } /** * Concatenates the elements of three Iterable sources sequentially *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the value type * @param source1 the first source, not null * @param source2 the second source, not null * @param source3 the third source, not null * @return the new Iterable source * @throws NullPointerException if any of the sources is null * @since 1.0 */ @SuppressWarnings("unchecked") public static Ix concat(Iterable source1, Iterable source2, Iterable source3) { return concatArray(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), nullCheck(source3, "source3 is null")); } /** * Concatenates the elements of three Iterable sources sequentially *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the value type * @param source1 the first source, not null * @param source2 the second source, not null * @param source3 the third source, not null * @param source4 the fourth source, not null * @return the new Iterable source * @throws NullPointerException if any of the sources is null * @since 1.0 */ @SuppressWarnings("unchecked") public static Ix concat(Iterable source1, Iterable source2, Iterable source3, Iterable source4) { return concatArray(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), nullCheck(source3, "source3 is null"), nullCheck(source4, "source4 is null")); } /** * Concatenates the elements of Iterable sources, provided as an array, sequentially. *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the common base type * @param sources the array of source Iterables * @return the new Ix instance * @throws NullPointerException if sources is null * @since 1.0 * @see #mergeArray(Iterable...) */ @SuppressWarnings("unchecked") public static Ix concatArray(Iterable... sources) { int n = sources.length; if (n == 0) { return empty(); } if (n == 1) { return from((Iterable)sources[0]); } return new IxFlattenArrayIterable((Iterable[])sources); } /** * Defers the generation of the actual Iterable till the iterator() is called on * the resulting Ix. *

* The result's iterator() forwards the remove() calls to the generated Iterable's Iterator. * @param the value type * @param factory the function that returns an Iterable when the resulting Ix.iterator() is called * @return the new Ix source * @throws NullPointerException if factory is null * @since 1.0 */ public static Ix defer(IxSupplier> factory) { return new IxDefer(nullCheck(factory, "factory is null")); } /** * No elements are emitted. *

* The result's iterator() doesn't support remove(). * @param the value type * @return the new Ix instance * @since 1.0 */ public static Ix empty() { return IxEmpty.instance(); } /** * Wraps the given Iterable source into an Ix instance (if * not already an Ix subclass). *

* The result's iterator() forwards the remove() calls to the source's * iterator(). * @param the value type * @param source the Iterable to wrap, not null * @return the new Ix instance * @throws NullPointerException if source is null * @since 1.0 */ public static Ix from(Iterable source) { if (source instanceof Ix) { return (Ix)source; } return new IxWrapper(nullCheck(source, "source")); } /** * Emits all the elements of the given array. *

* The result's iterator() doesn't support remove(). * @param the value type * @param values the array of values, not null * @return the new Ix instance * @throws NullPointerException if values is null * @since 1.0 */ public static Ix fromArray(T... values) { int n = values.length; if (n == 0) { return empty(); } if (n == 1) { return just(values[0]); } return new IxFromArray(0, values.length, values); } /** * Emits a range of elements from the given array. *

* The result's iterator() doesn't support remove(). * @param the value type * @param start the staring index, inclusive, non-negative * @param end the end index, exclusive, non-negative * @param values the array of values * @return the new Ix instance * @throws NullPointerException if values is null * @throws IndexOutOfBoundsException if either start or end are not in [0, values.length] * @since 1.0 */ public static Ix fromArrayRange(int start, int end, T... values) { if (start < 0 || end < 0 || start > values.length || end > values.length) { throw new IndexOutOfBoundsException("start=" + start + ", end=" + end + ", length=" + values.length); } return new IxFromArray(start, end, values); } /** * Generates a sequence of values via a generic indexed for-loop style construct; * the index starts with the given seed, checked via a condition (to terminate), * generated from the index via the selector and then a new index is generated via next. *

* The result's iterator() doesn't support remove(). * @param the index value type * @param the result value type * @param seed the initial value of the index * @param condition the receives the current index (before selector is called) and if it * returns false, the sequence terminates * @param next the function that receives the current index and returns the next index * @param selector the function that receives the current index and returns the value * to be emitted. * @return the new Ix instance * @throws NullPointerException if condition, next or selector is null * @since 1.0 */ public static Ix forloop(T seed, IxPredicate condition, IxFunction next, IxFunction selector) { return new IxForloop(seed, nullCheck(condition, "condition is null"), nullCheck(selector, "selector is null"), nullCheck(next, "next is null")); } /** * Calls the given action to generate a value or terminate whenever the next() * is called on the resulting Ix.iterator(). *

* The result's iterator() doesn't support remove(). *

* The action may call {@code onNext} at most once to signal the next value per action invocation. * The {@code onCompleted} should be called to indicate no further values will be generated (may be * called with an onNext in the same action invocation). Calling {@code onError} will immediately * throw the given exception (as is if it's a RuntimeException or Error; or wrapped into a RuntimeException). * @param the value type * @param nextSupplier the action called with an IxEmitter API to receive value, not null * @return the new Ix instance * @throws NullPointerException if nextSupplier is null * @since 1.0 */ public static Ix generate(IxConsumer> nextSupplier) { return new IxGenerateStateless(nullCheck(nextSupplier, "nextSupplier is null")); } /** * Calls the given function (with per-iterator state) to generate a value or terminate * whenever the next() is called on the resulting Ix.iterator(). *

* The result's iterator() doesn't support remove(). *

* The action may call {@code onNext} at most once to signal the next value per action invocation. * The {@code onCompleted} should be called to indicate no further values will be generated (may be * called with an onNext in the same action invocation). Calling {@code onError} will immediately * throw the given exception (as is if it's a RuntimeException or Error; or wrapped into a RuntimeException). * @param the value type * @param the state type supplied to and returned by the nextSupplier function * @param stateSupplier the function that returns a state for each invocation of iterator() * @param nextSupplier the action called with an IxEmitter API to receive value, not null * @return the new Ix instance * @throws NullPointerException if stateSupplier or nextSupplier is null * @since 1.0 */ public static Ix generate(IxSupplier stateSupplier, IxFunction2, S> nextSupplier) { return generate(stateSupplier, nextSupplier, IxEmptyAction.instance1()); } /** * Calls the given function (with per-iterator state) to generate a value or terminate * whenever the next() is called on the resulting Ix.iterator(). *

* The result's iterator() doesn't support remove(). *

* The action may call {@code onNext} at most once to signal the next value per action invocation. * The {@code onCompleted} should be called to indicate no further values will be generated (may be * called with an onNext in the same action invocation). Calling {@code onError} will immediately * throw the given exception (as is if it's a RuntimeException or Error; or wrapped into a RuntimeException). *

* Note that since there is no direct way to cancel an Iterator, the stateDisposer is only invoked * when the nextSupplier calls a terminal method. * @param the value type * @param the state type supplied to and returned by the nextSupplier function * @param stateSupplier the function that returns a state for each invocation of iterator() * @param nextSupplier the action called with an IxEmitter API to receive value, not null * @param stateDisposer the action called when the nextSupplier signals an {@code onError} or {@code onCompleted}. * @return the new Ix instance * @throws NullPointerException if stateSupplier, nextSupplier or stateDisposer is null * @since 1.0 */ public static Ix generate(IxSupplier stateSupplier, IxFunction2, S> nextSupplier, IxConsumer stateDisposer) { return new IxGenerate(nullCheck(stateSupplier, "stateSupplier is null"), nullCheck(nextSupplier, "nextSupplier is null"), nullCheck(stateDisposer, "stateDisposer is null")); } /** * Emits a single constant value. *

* The result's iterator() doesn't support remove(). * @param the value type * @param value the constant value to emit * @return the new Ix instance * @since 1.0 */ public static Ix just(T value) { return new IxJust(value); } /** * Concatenates the elements of Iterable sources, provided as an Iterable itself, sequentially. *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the common base type * @param sources the Iterable sequence of source Iterables * @return the new Ix instance * @throws NullPointerException if sources is null * @since 1.0 * @see #concat(Iterable) */ public static Ix merge(Iterable> sources) { return concat(sources); } /** * Concatenates the elements of Iterable sources, provided as an array, sequentially. *

* The result's iterator() forwards the remove() calls to the current iterator. *

* Note that merge and concat operations are the same in the Iterable world. * @param the common base type * @param sources the array of source Iterables * @return the new Ix instance * @throws NullPointerException if sources is null * @since 1.0 * @see #concatArray(Iterable...) */ public static Ix mergeArray(Iterable... sources) { return concatArray(sources); // concat and merge are the same in the Iterable world } /** * Merges self-comparable items from an Iterable sequence of Iterable sequences, picking * the smallest item from all those inner Iterables until all sources complete. * @param the value type * @param sources the Iterable sequence of Iterables of self-comparable items * @return the new Ix instance * @since 1.0 */ public static > Ix orderedMerge(Iterable> sources) { return orderedMerge(sources, SelfComparator.INSTANCE); } /** * Merges items from an Iterable sequence of Iterable sequences, picking * the smallest item (according to a custom comparator) from all those inner * Iterables until all sources complete. * @param the value type * @param sources the Iterable sequence of Iterables * @param comparator the comparator to compare items and pick the one that returns negative will be picked * @return the new Ix instance * @since 1.0 */ public static Ix orderedMerge(Iterable> sources, Comparator comparator) { return new IxOrderedMergeIterable(nullCheck(sources, "sources is null"), nullCheck(comparator, "comparator is null")); } /** * Merges self-comparable items from an Iterable sequence of Iterable sequences, picking * the smallest item from all those inner Iterables until all sources complete. * @param the value type * @param sources the Iterable sequence of Iterables of self-comparable items * @return the new Ix instance * @since 1.0 */ public static > Ix orderedMergeArray(Iterable... sources) { return orderedMergeArray(SelfComparator.INSTANCE, sources); } /** * Merges items from an array of Iterable sequences, picking * the smallest item (according to a custom comparator) from all those inner * Iterables until all sources complete. * @param the value type * @param sources the Iterable sequence of Iterables * @param comparator the comparator to compare items and pick the one that returns negative will be picked * @return the new Ix instance * @since 1.0 */ public static Ix orderedMergeArray(Comparator comparator, Iterable... sources) { return new IxOrderedMergeArray(nullCheck(sources, "sources is null"), nullCheck(comparator, "comparator is null")); } /** * Emits a range of incrementing integer values, starting from {@code start} and * up to {@code count} times. * @param start the starting value * @param count the number of integers to emit, non-negative * @return the new Ix instance * @throws IllegalArgumentException if count is negative * @since 1.0 */ public static Ix range(int start, int count) { if (count == 0) { return empty(); } if (count == 1) { return just(start); } if (count < 0) { throw new IllegalArgumentException("count >= 0 required but it was " + count); } return new IxRange(start, count); } /** * Prevents the downstream from calling remove() and throws * an UnsupportedOperationException instead. * @return the new Ix instance * @see #readOnly(boolean) * @since 1.0 */ public final Ix readOnly() { return new IxReadOnly(this, false); } /** * Prevents the downstream from calling remove() by optionally * ignoring it or throwing an UnsupportedOperationException. * @param silent if true, remove() calls are ignored; if false, * remove() calls throw an UnsupportedOperationException * @return the new Ix instance * @since 1.0 */ public final Ix readOnly(boolean silent) { return new IxReadOnly(this, silent); } /** * Repeatedly calls the given callable indefinitely and * emits the returned value. *

* The result's iterator() doesn't support remove(). * @param the value type * @param callable the callable to call * @return the new Ix instance * @since 1.0 */ public static Ix repeatCallable(Callable callable) { return new IxRepeatCallable(nullCheck(callable, "callable is null")); } /** * Repeats the given value indefinitely. *

* The result's iterator() doesn't support remove(). * @param the value type * @param value the value to emit whenever next() is called * @return the new Ix instance * @since 1.0 */ public static Ix repeatValue(T value) { return new IxRepeat(value); } /** * Repeats the given value at most count times. *

* A count of zero will yield an empty sequence, a count of one * will yield a sequence with only one element and so forth. *

* The result's iterator() doesn't support remove(). * @param the value type * @param value the value to emit * @param count the number of times to emit the value, non-negative * @return the new Ix instance * @throws IllegalArgumentException if count is negative * @since 1.0 */ public static Ix repeatValue(T value, long count) { return new IxRepeatCount(value, nonNegative(count, "count")); } /** * Repeats the given value until the given predicate returns true. *

* A count of zero will yield an empty sequence, a count of one * will yield a sequence with only one element and so forth. *

* The result's iterator() doesn't support remove(). * @param the value type * @param value the value to emit * @param stopPredicate the predicate called before any emission; returning * false keeps repeating the value, returning true terminates the sequence * @return the new Ix instance * @throws NullPointerException if stopPredicate is null * @since 1.0 */ public static Ix repeatValue(T value, IxBooleanSupplier stopPredicate) { return repeatValue(value, Long.MAX_VALUE, stopPredicate); } /** * Repeats the given value at most count times or until the given predicate returns true. *

* A count of zero will yield an empty sequence, a count of one * will yield a sequence with only one element and so forth. *

* The result's iterator() doesn't support remove(). * @param the value type * @param value the value to emit * @param count the number of times to emit the value, non-negative * @param stopPredicate the predicate called before any emission; returning * false keeps repeating the value, returning true terminates the sequence * @return the new Ix instance * @throws IllegalArgumentException if count is negative * @throws NullPointerException if stopPredicate is null * @since 1.0 */ public static Ix repeatValue(T value, long count, IxBooleanSupplier stopPredicate) { return new IxRepeatPredicate(value, nonNegative(count, "count"), nullCheck(stopPredicate, "stopPredicate is null")); } /** * Emits a sequence of substring of a string split by the given separator. *

* The result's iterator() doesn't support remove(). * @param string the string to split, not null * @param by the separator to split along, not null * @return the new Ix instance * @throws NullPointerException if string or by is null * @since 1.0 */ public static Ix split(String string, String by) { return new IxSplit(nullCheck(string, "string is null"), nullCheck(by, "by is null")); } /** * Combines the next element from each source Iterable via a zipper function. *

* If one of the source Iterables is sorter the sequence terminates eagerly. *

* The result's iterator() doesn't support remove(). * * @param the common element type of the sources * @param the result value type * @param sources the array of Iterable sources, not null * @param zipper the function that takes an array of values and returns a value * to be emitted, one from each source, not null * @return the new Ix instance * @throws NullPointerException if sources or zipper is null * @since 1.0 */ public static Ix zip(Iterable[] sources, IxFunction zipper) { return new IxZipArray(nullCheck(sources, "sources is null"), nullCheck(zipper, "zipper is null")); } /** * Combines the next element from each source Iterable, provided as an Iterable itself, * via a zipper function. *

* If one of the source Iterables is sorter the sequence terminates eagerly. *

* The result's iterator() doesn't support remove(). * * @param the common element type of the sources * @param the result value type * @param sources the Iterable of Iterable sources, not null * @param zipper the function that takes an array of values and returns a value * to be emitted, one from each source, not null * @return the new Ix instance * @throws NullPointerException if sources or zipper is null * @since 1.0 */ public static Ix zip(Iterable> sources, IxFunction zipper) { return new IxZipIterable(nullCheck(sources, "sources is null"), nullCheck(zipper, "zipper is null")); } /** * Combines the next element from each source Iterable via a zipper function. *

* If one of the source Iterables is sorter the sequence terminates eagerly. *

* The result's iterator() doesn't support remove(). * * @param the first source's element type * @param the second source's element type * @param the result value type * @param source1 the first source Iterable * @param source2 the second source Iterable * @param zipper the function that takes one from each source, not null * @return the new Ix instance * @throws NullPointerException if any of the sources or zipper is null * @since 1.0 */ public static Ix zip( Iterable source1, Iterable source2, IxFunction2 zipper) { return new IxZip2(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), nullCheck(zipper, "zipper is null")); } /** * Combines the next element from each source Iterable via a zipper function. *

* If one of the source Iterables is sorter the sequence terminates eagerly. *

* The result's iterator() doesn't support remove(). * * @param the first source's element type * @param the second source's element type * @param the third source's element type * @param the result value type * @param source1 the first source Iterable * @param source2 the second source Iterable * @param source3 the third source Iterable * @param zipper the function that takes one from each source, not null * @return the new Ix instance * @throws NullPointerException if any of the sources or zipper is null * @since 1.0 */ public static Ix zip( Iterable source1, Iterable source2, Iterable source3, IxFunction3 zipper) { return new IxZip3(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), nullCheck(source3, "source3 is null"), nullCheck(zipper, "zipper is null")); } /** * Combines the next element from each source Iterable via a zipper function. *

* If one of the source Iterables is sorter the sequence terminates eagerly. *

* The result's iterator() doesn't support remove(). * * @param the first source's element type * @param the second source's element type * @param the third source's element type * @param the fourth source's element type * @param the result value type * @param source1 the first source Iterable * @param source2 the second source Iterable * @param source3 the third source Iterable * @param source4 the fourth source Iterable * @param zipper the function that takes one from each source, not null * @return the new Ix instance * @throws NullPointerException if any of the sources or zipper is null * @since 1.0 */ public static Ix zip( Iterable source1, Iterable source2, Iterable source3, Iterable source4, IxFunction4 zipper) { return new IxZip4(nullCheck(source1, "source1 is null"), nullCheck(source2, "source2 is null"), nullCheck(source3, "source3 is null"), nullCheck(source4, "source4 is null"), nullCheck(zipper, "zipper is null")); } //--------------------------------------------------------------------------------------- // Instance operators //--------------------------------------------------------------------------------------- /** * Emits true if all elements of this sequence match a given predicate (including empty). *

* The result's iterator() doesn't support remove(). * @param predicate the predicate receiving each element * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 */ public final Ix all(IxPredicate predicate) { return new IxAll(this, nullCheck(predicate, "predicate is null")); } /** * Emits true if any element of this sequence matches the given predicate, * false otherwise (or for empty sequences). *

* The result's iterator() doesn't support remove(). * @param predicate the predicate receiving each element * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 */ public final Ix any(IxPredicate predicate) { return new IxAny(this, nullCheck(predicate, "predicate is null")); } /** * Calls the given transformers with this and returns its value allowing * fluent conversions to non-Ix types. * @param the result type * @param transformer the function receiving this Ix instance and returns a value * @return the value returned by the transformer function * @throws NullPointerException if transformer is null * @since 1.0 */ public final R as(IxFunction, R> transformer) { return transformer.apply(this); } /** * Calculates the float-based average of this sequence of numbers. *

The returned sequence is empty if this sequence is empty. *

This operator force-casts this sequence which may lead * to ClassCastException if any of this sequence's elements is not * a subclass of Number. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix averageFloat() { return new IxAverageFloat((Iterable)this); } /** * Calculates the double-based average of this sequence of numbers. *

The returned sequence is empty if this sequence is empty. *

This operator force-casts this sequence which may lead * to ClassCastException if any of this sequence's elements is not * a subclass of Number. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix averageDouble() { return new IxAverageDouble((Iterable)this); } /** * Buffers the subsequent {@code size} elements into a sequence of * non-overlapping Lists. *

* The result's iterator() doesn't support remove(). * @param size the number of elements to group together, positive * @return the new Ix instance * @throws IllegalArgumentException if size is non-positive * @since 1.0 */ public final Ix> buffer(int size) { return new IxBuffer(this, positive(size, "size")); } /** * Buffers the subsequent {@code size} elements into a sequence of * potentially overlapping Lists. *

* The result's iterator() doesn't support remove(). * @param size the number of elements to group together, positive * @param skip specifies how often to start a new list * @return the new Ix instance * @throws IllegalArgumentException if size or skip is non-positive * @since 1.0 */ public final Ix> buffer(int size, int skip) { if (size == skip) { return buffer(size); } if (size < skip) { return new IxBufferSkip(this, positive(size, "size"), positive(skip, "skip")); } return new IxBufferOverlap(this, positive(size, "size"), positive(skip, "skip")); } /** * Buffer until an item is encountered for which the predicate returns true, * triggering a new buffer. *

Neither the previous nor the next buffer will contain the item that caused the * split * @param predicate the predicate called with each item and should return false * to trigger a new buffer * @return the new Ix instance * @see #bufferUntil(IxPredicate) * @see #bufferWhile(IxPredicate) * @since 1.0 */ public final Ix> bufferSplit(IxPredicate predicate) { return new IxBufferSplit(this, nullCheck(predicate, "predicate is null")); } /** * Buffer until an item is encountered after which the predicate returns true * to start a new buffer. *

The item will be part of the previous buffer. * @param predicate the predicate called with each item after the item * has been added to the current buffer and should return true to start a new buffer * @return the new Ix instance * @see #bufferSplit(IxPredicate) * @see #bufferWhile(IxPredicate) * @since 1.0 */ public final Ix> bufferUntil(IxPredicate predicate) { return new IxBufferUntil(this, nullCheck(predicate, "predicate is null")); } /** * Buffer while an item is encountered before which the predicate returns false * to start a new buffer. *

The item will be part of the next buffer * @param predicate the predicate called with each item after the item * has been added to the current buffer and should return true to start a new buffer * @return the new Ix instance * @see #bufferSplit(IxPredicate) * @see #bufferUntil(IxPredicate) * @since 1.0 */ public final Ix> bufferWhile(IxPredicate predicate) { return new IxBufferWhile(this, nullCheck(predicate, "predicate is null")); } /** * Cast the elements to the specified class. *

* Note that this is a forced cast on this Ix instance and if * not compatible, a ClassCastException might be thrown downstream. * @param the target type * @param clazz the type token to capture the target type * @return the new Ix instance * @since 1.0 */ @SuppressWarnings({ "rawtypes", "unchecked" }) public final Ix cast(Class clazz) { return (Ix)this; } /** * Collect the elements into a collection via collector action and emit that collection * as a single item. *

* The result's iterator() doesn't support remove(). * @param the collection type * @param initialFactory the function returning a collection for each iterator() call * @param collector the action called with the collection and the current item * @return the new Ix instance * @throws NullPointerException if initialFactory or collector is null * @since 1.0 */ public final Ix collect(IxSupplier initialFactory, IxConsumer2 collector) { return new IxCollect(this, nullCheck(initialFactory, "initialFactory is null"), nullCheck(collector, "collector")); } /** * Collects the elements of this sequence into an Object array. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix collectToArray() { return collect(ToListHelper.initialFactory(), ToListHelper.collector()) .map(ToListHelper.toArray()); } /** * Collects the elements of this sequence into a List. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix> collectToList() { return collect(ToListHelper.initialFactory(), ToListHelper.collector()); } /** * Collects the elements of this sequence into a Map where the key is * determined from each element via the keySelector function; duplicates are * overwritten. *

* The result's iterator() doesn't support remove(). * @param the key type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @return the new Ix instance * @throws NullPointerException if keySelector is null * @since 1.0 */ public final Ix> collectToMap(IxFunction keySelector) { IxFunction f = IdentityHelper.instance(); return this.collectToMap(keySelector, f); } /** * Collects the elements of this sequence into a Map where the key is * determined from each element via the keySelector function and * the value is derived from the same element via the valueSelector function; duplicates are * overwritten. *

* The result's iterator() doesn't support remove(). * @param the key type * @param the value type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @param valueSelector the function that receives the current element and returns * a value for it to be used as the Map value * @return the new Ix instance * @throws NullPointerException if keySelector or valueSelector is null * @since 1.0 */ public final Ix> collectToMap(IxFunction keySelector, IxFunction valueSelector) { return new IxToMap(this, nullCheck(keySelector, "keySelector is null"), nullCheck(valueSelector, "valueSelector is null")); } /** * Collects the elements of this sequence into a multi-Map where the key is * determined from each element via the keySelector function. *

* The result's iterator() doesn't support remove(). * @param the key type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @return the new Ix instance * @throws NullPointerException if keySelector is null * @since 1.0 */ public final Ix>> collectToMultimap(IxFunction keySelector) { IxFunction f = IdentityHelper.instance(); return this.collectToMultimap(keySelector, f); } /** * Collects the elements of this sequence into a multi-Map where the key is * determined from each element via the keySelector function and * the value is derived from the same element via the valueSelector function. *

* The result's iterator() doesn't support remove(). * @param the key type * @param the value type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @param valueSelector the function that receives the current element and returns * a value for it to be used as the Map value * @return the new Ix instance * @throws NullPointerException if keySelector or valueSelector is null * @since 1.0 */ public final Ix>> collectToMultimap(IxFunction keySelector, IxFunction valueSelector) { return new IxToMultimap(this, keySelector, valueSelector); } /** * Collects the elements of this sequence into a Set. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix> collectToSet() { return new IxToSet(this); } /** * When the iterator() of the returned Ix is called, it calls the transformer function * with this Ix instance and emits the elements of the returned Iterable. *

* The result's iterator() forwards the call remove() to the returned Iterable's Iterator. * * @param the result value type * @param transformer the transformer called with this Ix when Ix.iterator() is invoked * @return the new Ix instance * @throws NullPointerException if transformer is null * @since 1.0 */ public final Ix compose(IxFunction, ? extends Iterable> transformer) { return new IxCompose(this, nullCheck(transformer, "transformer is null")); } /** * Maps each element from this sequence into subsequent Iterable sequences whose elements are * concatenated in order. *

* Note that flatMap and concatMap operations are the same in the Iterable world. *

* The result's iterator() forwards the call remove() to the current inner Iterator. * * @param the result value type * @param mapper the function * @return the new Ix instance * @throws NullPointerException if mapper is null * @since 1.0 * @see #flatMap(IxFunction) */ public final Ix concatMap(IxFunction> mapper) { return new IxFlattenIterable(this, nullCheck(mapper, "mapper is null")); } /** * Emits elements of this sequence followed by the elements of the other sequence. *

* Note that mergeWith and concatWith operations are the same in the Iterable world. *

* The result's iterator() forwards the call remove() to the current Iterator. * @param other the other sequence to emits elements of * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 * @see #mergeWith(Iterable) */ public final Ix concatWith(Iterable other) { return concat(this, other); } /** * Emits true if the sequence contains the given Object, compared via null-safe * equals. *

* The result's iterator() doesn't support remove(). * @param o the value to find * @return the new Ix instance * @since 1.0 */ public final Ix contains(Object o) { return new IxContains(this, o); } /** * Emits the number of elements in this sequence. *

* The result's iterator() doesn't support remove(). * @return the number of elements in this sequence * @since 1.0 */ public final Ix count() { return new IxCount(this); } /** * Emits the number of elements, as a long, in this sequence. *

* The result's iterator() doesn't support remove(). * @return the number of elements in this sequence * @since 1.0 */ public final Ix countLong() { return new IxCountLong(this); } /** * Emits the given value if this sequence is empty, streams this sequence otherwise. *

* The result's iterator() doesn't support remove(). * @param value the value to emit if this sequence is empty * @return the new Ix instance * @since 1.0 */ public final Ix defaultIfEmpty(T value) { return switchIfEmpty(Ix.just(value)); } /** * Emits only distinct, never before seen elements (according to null-safe equals()) * of this sequence. *

* Note that this operator uses a memory of seen elements which may grow unbounded * with long sequences. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix distinct() { return distinct(IdentityHelper.instance()); } /** * Emits only distinct, never before seen keys extracted from elements * (according to null-safe equals()) of this sequence. *

* Note that this operator uses a memory of seen elements which may grow unbounded * with long sequences. *

* The result's iterator() doesn't support remove(). * @param the key type * @param keySelector the function taking the current element and returning a key object * that will be compared with null-safe equals(). * @return the new Ix instance * @throws NullPointerException if keySelector is null * @since 1.0 */ public final Ix distinct(IxFunction keySelector) { return new IxDistinct(this, nullCheck(keySelector, "keySelector is null")); } /** * Emits elements from this sequence if each element is different from the previous element * (according to a null-safe equals()), dropping elements that evaluate to the same as the previous. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix distinctUntilChanged() { return distinctUntilChanged(IdentityHelper.instance()); } /** * Emits elements from this sequence if each element is different from the previous element * (according to a comparer), dropping elements that evaluate to the same as the previous. *

* The result's iterator() doesn't support remove(). * @param comparer the predicate receiving the previous element and the current element and * returns true if they are the same (thus ignoring the latter). * @return the new Ix instance * @throws NullPointerException if comparer is null * @since 1.0 */ public final Ix distinctUntilChanged(IxPredicate2 comparer) { return new IxDistinctUntilChanged(this, IdentityHelper.instance(), nullCheck(comparer, "comparer is null")); } /** * Emits elements from this sequence if each element is different from the previous element * (according to a null-safe equals() of the extracted key), dropping elements that evaluate * to the same as the previous. *

* The result's iterator() doesn't support remove(). * @param the key type * @param keySelector the function that receives the current element and returns a key that will be compared * via null-safe equals with the previous element's key * @return the new Ix instance * @throws NullPointerException if comparer is null * @since 1.0 */ public final Ix distinctUntilChanged(IxFunction keySelector) { return new IxDistinctUntilChanged(this, keySelector, EqualityHelper.INSTANCE); } /** * Calls the given action just before when the consumer calls next() of this Ix.iterator(). *

* The result's iterator() forwards calls to remove() to this Iterator. * @param action the action to call for each item * @return the new Ix instance * @throws NullPointerException if action is null * @since 1.0 */ public final Ix doOnNext(IxConsumer action) { return new IxDoOn(this, nullCheck(action, "action is null"), IxEmptyAction.instance0()); } /** * Calls the given action after consumption of this sequence has completed, i.e., when * hasNext() of this Ix.iterator() returns false. *

* The result's iterator() forwards calls to remove() to this' Iterator. * @param action the action to call after the source sequence completes * @return the new Ix instance * @throws NullPointerException if action is null * @since 1.0 */ public final Ix doOnCompleted(Runnable action) { return new IxDoOn(this, IxEmptyAction.instance1(), nullCheck(action, "action is null")); } /** * Emits the elements of this sequence followed by the elements of the given array of values. *

* The result's iterator() doesn't support remove(). * @param values the elements to emit after this sequence * @return the new Ix instance * @throws NullPointerException if values is null * @since 1.0 */ public final Ix endWith(T... values) { return concat(this, fromArray(values)); } /** * Emit every Nth item only from upstream. *

Example: Ix.range(1, 5).every(2) will yield {2, 4}. * @param nth how many items to skip + 1 * @return the new Ix instance * @since 1.0 */ public final Ix every(int nth) { return new IxEvery(this, positive(nth, "nth")); } /** * Emits distinct elements from this and the other Iterable which are not * in the other sequence (i.e., (A union B) minus (A intersection B)). *

* The result's iterator() doesn't support remove(). * @param other the other Iterable sequence, not null * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 * @see #union(Iterable) * @see #intersect(Iterable) */ public final Ix except(Iterable other) { return new IxExcept(this, nullCheck(other, "other is null")); } /** * Emits elements of this sequence which match the given predicate only. *

* The result's iterator() forwards the call to remove() to this' Iterator. * @param predicate the predicate receiving the current element and if it * returns true, the value is emitted, ignored otherwise. * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 */ public final Ix filter(IxPredicate predicate) { return new IxFilter(this, nullCheck(predicate, "predicate is null")); } /** * Maps each element from this sequence into subsequent Iterable sequences whose elements are * concatenated in order. *

* Note that flatMap and concatMap operations are the same in the Iterable world. *

* The result's iterator() forwards the call remove() to the current inner Iterator. * * @param the result value type * @param mapper the function * @return the new Ix instance * @throws NullPointerException if mapper is null * @since 1.0 * @see #concatMap(IxFunction) */ public final Ix flatMap(IxFunction> mapper) { return new IxFlattenIterable(this, mapper); } /** * Groups elements of this sequence into distinct groups keyed by the keys returned by the keySelector. *

* The operator doesn't lose data and calling hasNext/next on either the returned Ix or on the inner * GroupedIx can move the source sequence forward. *

* The result's iterator() and the inner groups' Iterators don't support remove(). * @param the key type * @param keySelector the function receiving the current element and returns the key to be used for * grouping the values into the same inner GroupedIx. * @return the new Ix instance * @throws NullPointerException if keySelector is null * @since 1.0 * @see #groupBy(IxFunction, IxFunction) */ public final Ix> groupBy(IxFunction keySelector) { return groupBy(keySelector, IdentityHelper.instance()); } /** * Groups mapped elements (by the valueSelector) of this sequence into distinct groups * keyed by the keys returned by the keySelector. *

* The operator doesn't lose data and calling hasNext/next on either the returned Ix or on the inner * GroupedIx can move the source sequence forward. *

* The result's iterator() and the inner groups' Iterators don't support remove(). * @param the key type * @param the value type * @param keySelector the function receiving the current element and returns the key to be used for * grouping the values into the same inner GroupedIx. * @param valueSelector the function receiving the current element and returns the value to be emitted * by the appropriate group * @return the new Ix instance * @throws NullPointerException if keySelector or valueSelector is null * @since 1.0 * @see #groupBy(IxFunction, IxFunction) */ public final Ix> groupBy(IxFunction keySelector, IxFunction valueSelector) { return new IxGroupBy(this, nullCheck(keySelector, "keySelector is null"), nullCheck(valueSelector, "valueSelector is null")); } /** * Emits true if this sequence has elements, emits false otherwise. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix hasElements() { return new IxHasElements(this); } /** * Hides the identity of this Ix instance and prevents certain identity-based optimizations. *

* The result's iterator() forwards the remove() calls to this' Iterator. * @return the new Ix instance * @since 1.0 */ public final Ix hide() { return new IxWrapper(this); } /** * Emits distinct values of this and the other Iterables that are present in * both sequences. *

* The result's iterator() doesn't support remove(). * @param other the other Iterable sequence * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 * @see #except(Iterable) * @see #union(Iterable) */ public final Ix intersect(Iterable other) { return new IxIntersect(this, nullCheck(other, "other is null")); } /** * Runs through this sequence, ignoring all values until this sequence completes. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix ignoreElements() { return new IxIgnoreElements(this); } /** * Converts elements of this sequence to String and concatenates them into * a single, comma separated String. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix join() { return join(", "); } /** * Converts elements of this sequence to String and concatenates them into * a single String separated by the given character sequence. *

* The result's iterator() doesn't support remove(). * @param separator the character sequence separating elements * @return the new Ix instance * @since 1.0 */ public final Ix join(CharSequence separator) { return new IxJoin(this, separator); } /** * Calls the given lifter function with the iterator of this sequence and emits * elements of the returned Iterator. *

* The result's iterator() forwards the remove() calls to the returned Iterator. * @param the result value type * @param lifter the function that receives the Iterator of this and returns an Iterator * that will be consumed further on * @return the new Ix instance * @throws NullPointerException if lifter is null * @since 1.0 */ public final Ix lift(IxFunction, ? extends Iterator> lifter) { return new IxLift(this, nullCheck(lifter, "lifter is null")); } /** * Maps each element of this sequence to some other value. *

* The result's iterator() forwards the remove() calls to this' Iterator. * @param the result value type * @param mapper the function that receives an element from this sequence * and returns another value for it to be emitted. * @return the new Ix instance * @throws NullPointerException if mapper is null * @since 1.0 */ public final Ix map(IxFunction mapper) { return new IxMap(this, mapper); } /** * Emits the first maximum element according to the given comparator. *

* The result's iterator() doesn't support remove(). * @param comparator the comparator called with the latest maximum element and * the current element; if it returns a positive value, the current element * becomes the maximum element. * @return the new Ix instance * @throws NullPointerException if comparator is null * @since 1.0 * @see #min(Comparator) */ public final Ix max(Comparator comparator) { return new IxMinMax(this, comparator, -1); } /** * Emits the first maximum element according to their natural order. *

* The sequence may throw a ClassCastException if any of the elements is * not self-comparable (i.e., doesn't implement the Comparable interface). *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 * @see #min() */ @SuppressWarnings({ "rawtypes", "unchecked" }) public final Ix max() { return max((Comparator)SelfComparator.INSTANCE); } /** * Returns the first maximum integer value. *

* The sequence may throw a ClassCastException if any of the elements is not * an Integer object. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix maxInt() { return new IxMaxInt((Ix)this); } /** * Returns the first maximum long value. *

* The sequence may throw a ClassCastException if any of the elements is not * a Long object. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix maxLong() { return new IxMaxLong((Ix)this); } /** * Emits elements of this sequence followed by the elements of the other sequence. *

* Note that mergeWith and concatWith operations are the same in the Iterable world. *

* The result's iterator() forwards the call remove() to the current Iterator. * @param other the other sequence to emits elements of * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 * @see #concatWith(Iterable) */ public final Ix mergeWith(Iterable other) { return concatWith(other); } /** * Emits the first minimum element according to the given comparator. *

* The result's iterator() doesn't support remove(). * @param comparator the comparator called with the latest minimum element and * the current element; if it returns a negative value, the current element * becomes the minimum element. * @return the new Ix instance * @throws NullPointerException if comparator is null * @since 1.0 * @see #max(Comparator) */ public final Ix min(Comparator comparator) { return new IxMinMax(this, comparator, 1); } /** * Emits the first minimum element according to their natural order. *

* The sequence may throw a ClassCastException if any of the element is * not self-comparable (i.e., doesn't implement the Comparable interface). *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 * @see #min() */ @SuppressWarnings({ "rawtypes", "unchecked" }) public final Ix min() { return min((Comparator)SelfComparator.INSTANCE); } /** * Returns the first minimum integer value. *

* The sequence may throw a ClassCastException if any of the elements is not * an Integer object. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix minInt() { return new IxMinInt((Ix)this); } /** * Returns the first minimum long value. *

* The sequence may throw a ClassCastException if any of the elements is not * a Long object. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix minLong() { return new IxMinLong((Ix)this); } /** * Orders elements according to their natural order. *

* The sequence may throw a ClassCastException if any of the elements is not * a self-comparable object (i.e., doesn't implement the Comparable interface). *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 * @see #orderByReverse() * @see #orderBy(Comparator) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public final Ix orderBy() { return orderBy((Comparator)SelfComparator.INSTANCE); } /** * Orders elements according to the comparator. *

* The result's iterator() doesn't support remove(). * @param comparator the comparator comparing two elements; if it returns a negative value, * the first element will be before the second; if it returns a positive value, * the first element will be after the second. * @return the new Ix instance * @throws NullPointerException if comparator is null * @since 1.0 * @see #orderBy() * @see #orderByReverse(Comparator) */ public final Ix orderBy(Comparator comparator) { return new IxOrderBy(this, IdentityHelper.instance(), nullCheck(comparator, "comparator is null"), 1); } /** * Orders elements according to the natural order of the extracted keys from these elements. *

* The result's iterator() doesn't support remove(). * @param the key type * @param keySelector the function receiving each element and returns a self-comparable key for them. * @return the new Ix instance * @throws NullPointerException if keySelector is null * @since 1.0 * @see #orderByReverse(IxFunction) */ public final > Ix orderBy(IxFunction keySelector) { return new IxOrderBy(this, nullCheck(keySelector, "keySelector is null"), SelfComparator.INSTANCE, 1); } /** * Orders elements according to their reverse natural order. *

* The sequence may throw a ClassCastException if any of the elements is not * a self-comparable object (i.e., doesn't implement the Comparable interface). *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 * @see #orderBy() * @see #orderByReverse(Comparator) */ @SuppressWarnings({ "unchecked", "rawtypes" }) public final Ix orderByReverse() { return orderByReverse((Comparator)SelfComparator.INSTANCE); } /** * Orders elements according to the reversed comparator. *

* The result's iterator() doesn't support remove(). * @param comparator the comparator comparing two elements; if it returns a negative value, * the first element will be after the second; if it returns a positive value, * the first element will be before the second. * @return the new Ix instance * @throws NullPointerException if comparator is null * @since 1.0 * @see #orderByReverse() * @see #orderBy(Comparator) */ public final Ix orderByReverse(Comparator comparator) { return new IxOrderBy(this, IdentityHelper.instance(), nullCheck(comparator, "comparator is null"), -1); } /** * Orders elements according to the reverse natural order of the extracted keys from these elements. *

* The result's iterator() doesn't support remove(). * @param the key type * @param keySelector the function receiving each element and returns a self-comparable key for them. * @return the new Ix instance * @throws NullPointerException if keySelector is null * @since 1.0 * @see #orderByReverse(IxFunction) */ public final > Ix orderByReverse(IxFunction keySelector) { return new IxOrderBy(this, nullCheck(keySelector, "keySelector is null"), SelfComparator.INSTANCE, -1); } /** * Shares an underlying Iterator that is consumed only once and each created iterator() that calls * next() will receive the elements; other iterator() instances may receive different or no elements * at all. *

* The result's iterator() doesn't support remove(). * @return the new iterator sequence * @since 1.0 */ public final Ix publish() { return new IxPublish(this); } /** * Shares an Iterator, exposed as an Ix sequence, for the duration of the transform function called * for each iterator() invocation and emits elements of the resulting iterable sequence of the function. *

* The result's iterator() doesn't support remove(). * @param the result value type * @param transform the function that receives an Ix instance sharing a single underlying Iterator to this * sequence and returns another Iterable to be the result sequence * @return the new Iterable sequence * @throws NullPointerException if transform is null * @since 1.0 */ public final Ix publish(IxFunction, ? extends Iterable> transform) { return new IxPublishSelector(this, nullCheck(transform, "transform is null")); } /** * Reduces the elements of this sequence into a single value via a reducer function. *

* The result's iterator() doesn't support remove(). * @param reducer the function that receives the previous reduced element (or the first) and the current element * and returns a new reduced element * @return the new Ix instance * @throws NullPointerException if reducer is null * @since 1.0 * @see #reduce(IxSupplier, IxFunction2) */ public final Ix reduce(IxFunction2 reducer) { return new IxAggregate(this, nullCheck(reducer, "reducer is null")); } /** * Given a per-iterator() initial value, reduces the elements of this sequence into a single * value via a reducer function. *

* The result's iterator() doesn't support remove(). * @param the reduced value type * @param initialFactory a function called for each iterator() invocation and returns the first * reduced value * @param reducer the function called with the previous (or initial) reduced value and the current element * and returns a new reduced value * @return the new Ix instance * @throws NullPointerException if initialFactory or reducer is null * @since 1.0 * @see #reduce(IxFunction2) */ public final Ix reduce(IxSupplier initialFactory, IxFunction2 reducer) { return new IxReduce(this, initialFactory, reducer); } /** * Removes those elements via Iterator.remove() from this sequence that match the * given predicate. *

* The result's iterator() forwards the calls to remove() to this' Iterator. * @param predicate the function called with the current element and returns true * if that particular element should be removed. * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 * @see #retain(IxPredicate) */ public final Ix remove(IxPredicate predicate) { return new IxRemove(this, nullCheck(predicate, "predicate is null")); } /** * Repeats this sequence indefinitely. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix repeat() { return concat(repeatValue(this)); } /** * Repeats this sequence at most the given number of times. *

A count of zero will yield an empty sequence, a count of one * will yield a sequence with only one element and so forth. *

* The result's iterator() doesn't support remove(). * @param times the number of times to emit the value, non-negative * @return the new Ix instance * @throws IllegalArgumentException if count is negative * @since 1.0 */ public final Ix repeat(long times) { return concat(repeatValue(this, times)); } /** * Repeats this sequence if the given predicate returns true after the sequence * completes in a round. *

* The result's iterator() doesn't support remove(). * @param stopPredicate the predicate called before any emission; returning * false keeps repeating the value, returning true terminates the sequence * @return the new Ix instance * @throws NullPointerException if stopPredicate is null * @since 1.0 */ public final Ix repeat(IxBooleanSupplier stopPredicate) { return concat(repeatValue(this, stopPredicate)); } /** * Repeats this sequence if the given predicate returns true after the sequence * completes in a round or at most the given number of times. *

* A count of zero will yield an empty sequence, a count of one * will yield a sequence with only one element and so forth. *

* The result's iterator() doesn't support remove(). * @param times the number of times to emit the value, non-negative * @param stopPredicate the predicate called before any emission; returning * false keeps repeating the value, returning true terminates the sequence * @return the new Ix instance * @throws IllegalArgumentException if count is negative * @throws NullPointerException if stopPredicate is null * @since 1.0 */ public final Ix repeat(long times, IxBooleanSupplier stopPredicate) { return concat(repeatValue(this, times, stopPredicate)); } /** * Caches and replays all elements of this sequence to consumers of this' iterator(). *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix replay() { return new IxReplay(this); } /** * Caches and replays the last {@code size} elements of this sequence to consumers of this' iterator(). *

* Consumption by any of the iterator() may move the source sequence forward and subsequent iterator() * consumers may get a different set of values *

* The result's iterator() doesn't support remove(). * @param size the maximum number of elements to keep replaying to new iterator() consumers, positive * @return the new Ix instance * @throws IllegalArgumentException if size is non-positive * @since 1.0 */ public final Ix replay(int size) { return new IxReplaySize(this, positive(size, "size")); } /** * Caches and replays the elements of this sequence for the duration of the given transform function * without consuming this sequence multiple times. *

* The result's iterator() doesn't support remove(). * @param the result value type * @param transform the function receiving a view into the cache and returns an Iterable sequence whose * elements will be emitted by this Ix. * @return the new Ix instance * @throws NullPointerException if transform is null * @since 1.0 */ public final Ix replay(IxFunction, ? extends Iterable> transform) { return new IxReplaySelector(this, nullCheck(transform, "transform is null")); } /** * Caches and replays the the last {@code size} elements of this sequence for the duration of the given transform function * without consuming this sequence multiple times. *

* Consumption by any of the inner Ix' iterator() may move the shared sequence forward and subsequent iterator() * consumers may get a different set of values *

* The result's iterator() doesn't support remove(). * @param the result value type * @param size the maximum number of elements to keep replaying to new inner Ix iterator() consumers, positive * @param transform the function receiving a view into the cache and returns an Iterable sequence whose * elements will be emitted by this Ix. * @return the new Ix instance * @throws NullPointerException if transform is null * @throws IllegalArgumentException if size is non-positive * @since 1.0 */ public final Ix replay(int size, IxFunction, ? extends Iterable> transform) { return new IxReplaySizeSelector(this, positive(size, "size"), nullCheck(transform, "transform is null")); } /** * Removes those elements via Iterator.remove() from this sequence that don't match the * given predicate. *

* The result's iterator() forwards the calls to remove() to this' Iterator. * @param predicate the function called with the current element and returns false * if that particular element should be removed. * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 * @see #remove(IxPredicate) */ public final Ix retain(IxPredicate predicate) { return new IxRetain(this, nullCheck(predicate, "predicate is null")); } /** * Plays this sequence in reverse. *

* The reversal requires consuming the entire sequence and doesn't work with * infinite sequences. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ public final Ix reverse() { return new IxReverse(this); } /** * Performs a running accumulation, that is, returns intermediate elements returned by the * scanner function. *

* The result's iterator() doesn't support remove(). * @param scanner the function that receives the previous (or first) accumulated element and the current * element and returns a value to be emitted and to become the accumulated element * @return the new Ix instance * @throws NullPointerException if scanner is null * @since 1.0 */ public final Ix scan(IxFunction2 scanner) { return new IxScan(this, nullCheck(scanner, "scanner is null")); } /** * Performs a running accumulation, that is, returns intermediate elements returned by the * scanner function, starting with a per-iterator initial value. *

* The result's iterator() doesn't support remove(). * @param the accumulated value type * @param initialFactory function called for each iterator() and returns the initial accumulator value * @param scanner the function that receives the previous (or first) accumulated element and the current * element and returns a value to be emitted and to become the accumulated element * @return the new Ix instance * @throws NullPointerException if initialFactory or scanner is null * @since 1.0 */ public final Ix scan(IxSupplier initialFactory, IxFunction2 scanner) { return new IxScanSeed(this, nullCheck(initialFactory, "initialFactory is null"), nullCheck(scanner, "scanner is null")); } /** * Determines if two sequences have the same elements in the same order and are the same length based * on null-safe object equality. *

* The result's iterator() doesn't support remove(). * @param other the other sequence to compare with * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 */ public final Ix sequenceEqual(Iterable other) { return sequenceEqual(nullCheck(other, "other is null"), EqualityHelper.INSTANCE); } /** * Determines if two sequences have the same elements in the same order and are the same length based * on the given comparer's boolean value. *

* The result's iterator() doesn't support remove(). * @param other the other sequence to compare with * @param comparer the predicate receiving elements from this and the other sequence and returns true if those * elements are equal * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 */ public final Ix sequenceEqual(Iterable other, IxPredicate2 comparer) { return new IxSequenceEqual(this, nullCheck(other, "other is null"), nullCheck(comparer, "comparer is null")); } /** * Skips the first n elements from this sequence. *

* The result's iterator() forwards the calls to remove() to this' Iterator. * @param n the elements to skip, non-positive values won't skip any elements * @return the new Ix instance * @since 1.0 * @see #take(int) */ public final Ix skip(int n) { if (n <= 0) { return this; } return new IxSkip(this, n); } /** * Skips the last n elements from this sequence. *

* The result's iterator() doesn't support remove(). * @param n the elements to skip, non-positive values won't skip any elements * @return the new Ix instance * @since 1.0 * @see #takeLast(int) */ public final Ix skipLast(int n) { if (n <= 0) { return this; } return new IxSkipLast(this, n); } /** * Skips the first elements while the given predicate returns true; once it returns false * all subsequent elements are emitted. *

* The result's iterator() forwards the calls to remove() to this' Iterator. * @param predicate the predicate called with the current element and returns true * to skip that element * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 * @see #takeWhile(IxPredicate) */ public final Ix skipWhile(IxPredicate predicate) { return new IxSkipWhile(this, nullCheck(predicate, "predicate is null")); } /** * Emits elements of the given array followed by the elements of this sequence. *

* The result's iterator() doesn't support remove(). * @param values the array of values to emit first * @return the new Ix instance * @throws NullPointerException if values is null * @since 1.0 */ public final Ix startWith(T... values) { return concat(fromArray(values), this); } /** * Sums values of this sequence as integer. *

* The operation may throw a ClassCastException if any of the elements * is not an Integer. *

* An empty sequence yields an empty sum. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix sumInt() { return new IxSumInt((Ix)this); } /** * Sums values of this sequence as long. *

* The operation may throw a ClassCastException if any of the elements * is not an Long. *

* An empty sequence yields an empty sum. *

* The result's iterator() doesn't support remove(). * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix sumLong() { return new IxSumLong((Ix)this); } /** * Emits the elements of the other sequence if this sequence is empty. *

* The result's Iterator forwards calls of remove() to this' or the other's Iterator. * @param other the other Iterable instance, not null * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 */ public final Ix switchIfEmpty(Iterable other) { return new IxSwitchIfEmpty(this, nullCheck(other, "other is null")); } /** * Emits the first n elements (or less) of this sequence. *

* The result's Iterator forwards calls of remove() to this' Iterator. * @param n the number of items to emit at most, non-negative * @return the new Ix instance * @throws IllegalArgumentException if n is negative * @since 1.0 * @see #skip(int) */ public final Ix take(int n) { return new IxTake(this, nonNegative(n, "n")); } /** * Emits the last n elements (or fewer) of this sequence. *

* The result's iterator() doesn't support remove(). * @param n the number of last elements to emit * @return the new Ix instance * @throws IllegalArgumentException if n is negative * @since 1.0 * @see #skipLast(int) */ public final Ix takeLast(int n) { return new IxTakeLast(this, nonNegative(n, "n")); } /** * Take elements from this sequence until the given predicate returns true * for the current element (checked after emission of that element). *

* The result's Iterator forwards calls of remove() to this' Iterator. * @param stopPredicate the function receiving the current element and returns * true if no further elements should be emitted after this element. * @return the new Ix instance * @throws NullPointerException if stopPredicate is null * @since 1.0 */ public final Ix takeUntil(IxPredicate stopPredicate) { return new IxTakeUntil(this, nullCheck(stopPredicate, "stopPredicate is null")); } /** * Take elements from this sequence while the given predicate returns true * for the current element (checked before emission of that element). *

* The result's Iterator forwards calls of remove() to this' Iterator. * @param predicate the function receiving the current element and returns * false if no further elements should be emitted (not even the current). * @return the new Ix instance * @throws NullPointerException if predicate is null * @since 1.0 */ public final Ix takeWhile(IxPredicate predicate) { return new IxTakeWhile(this, nullCheck(predicate, "predicate is null")); } /** * Maps this sequence of numbers into a sequence of longs. *

* The sequence may throw a ClassCastException if any of the elements * is not a subclass of Number. *

* The result's Iterator forwards calls of remove() to this' Iterator. * @return the new Ix instance * @since 1.0 */ @SuppressWarnings("unchecked") public final Ix toLong() { return ((Ix)this).map(NumberToLongHelper.INSTANCE); } /** * Allows working with the Iterator of this sequence and emit elements in * a more flexible way *

* The result's iterator() doesn't support remove(). * @param the result value type * @param transformer the functional interface whose moveNext is called with the * current Iterator and should signal a value to be emitted for it. * @return the new Ix instance * @throws NullPointerException if transformer is null */ public final Ix transform(IxTransform transformer) { return new IxTransformer(this, nullCheck(transformer, "transformer is null")); } /** * Emits a distinct set of values from both this and the other sequence. *

* The result's iterator() doesn't support remove(). * @param other the other Iterable sequence, not null * @return the new Ix instance * @throws NullPointerException if other is null * @since 1.0 * @see #except(Iterable) * @see #intersect(Iterable) */ public final Ix union(Iterable other) { return new IxUnion(this, nullCheck(other, "other is null")); } /** * Emits inner Ix Iterables of non-overlapping sequences mapped from this sequence * with the given maximum size each. * *

* The result's and the inner Ix' iterator() don't support remove(). * @param size the maximum size of the inner windows, positive * @return the new Ix instance * @throws IllegalArgumentException if size is non-positive * @since 1.0 * @see #window(int, int) */ public final Ix> window(int size) { return new IxWindow(this, positive(size, "size")); } /** * Emits inner Ix Iterables of potentially overlapping sequences mapped from this * sequence with the given maximum size each and started each {@code skip} source elements. * @param size the maximum size of the inner windows, positive * @param skip after how many elements to start a new window (repeatedly), positive * @return the new Ix instance * @throws IllegalArgumentException if size or skip is non-positive * @since 1.0 * @see #window(int) */ public final Ix> window(int size, int skip) { if (size == skip) { return window(size); } if (size < skip) { return new IxWindowSkip(this, positive(size, "size"), positive(skip, "skip")); } return new IxWindowOverlap(this, positive(size, "size"), positive(skip, "skip")); } /** * Combines the next element from this and the other source Iterable via a zipper function. *

* If one of the source Iterables is sorter the sequence terminates eagerly. *

* The result's iterator() doesn't support remove(). * * @param the other source's element type * @param the result value type * @param other the the other source Iterable * @param zipper the function that takes one from each source, not null * @return the new Ix instance * @throws NullPointerException if other or zipper is null * @since 1.0 */ public final Ix zipWith(Iterable other, IxFunction2 zipper) { return zip(this, other, zipper); } //--------------------------------------------------------------------------------------- // Leaving the Iterable world //--------------------------------------------------------------------------------------- /** * Returns the first element of this sequence. * @return the first element * @throws NoSuchElementException if this sequence is empty * @since 1.0 * @see #first(Object) * @see #last(Object) */ @SuppressWarnings("unchecked") public final T first() { if (this instanceof Callable) { return checkedCall((Callable) this); } return iterator().next(); } /** * Returns the first element of this sequence or the defaultValue * if this sequence is empty. * @param defaultValue the value to return if this sequence is empty * @return the first element or the default value * @since 1.0 * @see #first() * @see #last() */ @SuppressWarnings("unchecked") public final T first(T defaultValue) { if (this instanceof Callable) { return checkedCall((Callable) this); } Iterator it = iterator(); if (it.hasNext()) { return it.next(); } return defaultValue; } /** * Consumes the entire sequence and calls the given action with each value. * @param action the action to call * @throws NullPointerException if action is null * @since 1.0 * @see #foreachWhile(IxPredicate) */ public final void foreach(IxConsumer action) { for (T t : this) { action.accept(t); } } /** * Consumes the entire sequence and calls the given predicate with each value; * which can stop the iteration by returning false. * @param predicate the predicate to call with the current element and should * return true to continue the loop or false to quit the loop. * @throws NullPointerException if action is null * @since 1.0 * @see #foreach(IxConsumer) */ public final void foreachWhile(IxPredicate predicate) { for (T t : this) { if (!predicate.test(t)) { break; } } } /** * Consumes the entire sequence and adds each element into the given collection * that is also returned. * @param the collection of type accepting a (super)type of this element type * @param collection the collection to collect into * @return the collection itself * @throws NullPointerException if collection is null * @since 1.0 */ public final > U into(U collection) { for (T v : this) { collection.add(v); } return collection; } /** * Returns the last element of this sequence. * @return the last element of this sequence * @throws NoSuchElementException if the sequence is empty * @since 1.0 * @see #last(Object) */ @SuppressWarnings("unchecked") public final T last() { if (this instanceof Callable) { return checkedCall((Callable) this); } Iterator it = iterator(); if (!it.hasNext()) { throw new NoSuchElementException(); } for (;;) { T t = it.next(); if (!it.hasNext()) { return t; } } } /** * Returns the last element of this sequence or the defaultValue if * this sequence is empty. * @param defaultValue the value to return if this sequence is empty * @return the last element or the default value * @since 1.0 * @see #last() * @see #first() */ @SuppressWarnings("unchecked") public final T last(T defaultValue) { if (this instanceof Callable) { return checkedCall((Callable) this); } Iterator it = iterator(); if (!it.hasNext()) { return defaultValue; } for (;;) { T t = it.next(); if (!it.hasNext()) { return t; } } } /** * Prints the elements of this sequence to the console, separated * by a comma+space and with a line break after roughly 80 characters. * @since 1.0 */ public final void print() { print(", ", 80); } /** * Prints the elements of this sequence to the console, separated * by the given separator and with a line break after roughly the * given charsPerLine amount. * @param separator the characters to separate the elements * @param charsPerLine indicates how long a line should be */ public final void print(CharSequence separator, int charsPerLine) { boolean first = true; int len = 0; for (T v : this) { String s = String.valueOf(v); if (first) { System.out.print(s); len += s.length(); first = false; } else { System.out.print(separator); len += separator.length(); if (len > charsPerLine) { System.out.println(); System.out.print(s); len = s.length(); } else { System.out.print(s); len += s.length(); } } } } /** * Prints each element of this sequence into a new line on the console. * @since 1.0 */ public final void println() { for (T v : this) { System.out.println(v); } } /** * Prints each element of this sequence into a new line on the console, prefixed * by the given character sequence. * @param prefix the prefix before each line */ public final void println(CharSequence prefix) { for (T v : this) { System.out.print(prefix); System.out.println(v); } } /** * Removes all elements by repeatedly calling this sequence's Iterator.remove(). */ public final void removeAll() { Iterator it = iterator(); while (it.hasNext()) { it.next(); it.remove(); } } /** * Consumes this Iterable and removes all elements for * which the predicate returns true; in other words, * remove those elements of a mutable source that match * the predicate. * @param predicate the predicate called with the current * element and should return true for elements to remove, false * for elements to keep. * @throws UnsupportedOperationException if the this Iterable * doesn't allow removing elements. * @see #retainAll(IxPredicate) * @see #removeAll() * @since 1.0 */ public final void removeAll(IxPredicate predicate) { Iterator it = iterator(); while (it.hasNext()) { T v = it.next(); if (predicate.test(v)) { it.remove(); } } } /** * Consumes this Iterable and removes all elements for * which the predicate returns false; in other words, * retain those elements of a mutable source that match * the predicate. * @param predicate the predicate called with the current * element and should return true for elements to keep, false * for elements to remove. * @throws UnsupportedOperationException if the this Iterable * doesn't allow removing elements. * @see #removeAll(IxPredicate) * @since 1.0 */ public final void retainAll(IxPredicate predicate) { Iterator it = iterator(); while (it.hasNext()) { T v = it.next(); if (!predicate.test(v)) { it.remove(); } } } /** * Iterates over this instance, dropping all values it produces. * @see #subscribe() */ public final void run() { Iterator it = iterator(); while (it.hasNext()) { it.next(); } } /** * Returns the single element of this sequence or throws a NoSuchElementException * if this sequence is empty or IndexOutOfBoundsException if this sequence has more * than on element * @return the single element of the sequence * @throws IndexOutOfBoundsException if the sequence has more than one element * @throws NoSuchElementException if the sequence is empty * @since 1.0 * @see #single(Object) */ public final T single() { Iterator it = iterator(); if (it.hasNext()) { T v = it.next(); if (it.hasNext()) { throw new IndexOutOfBoundsException("The source has more than one element."); } return v; } throw new NoSuchElementException("The source is empty."); } /** * Returns the single element of this sequence, defaultValue * if this sequence is empty or IndexOutOfBoundsException if this sequence has more * than one element * @param defaultValue the value to return if this sequence is empty * @return the single element of the sequence * @throws IndexOutOfBoundsException if the sequence has more than one element * @since 1.0 * @see #single(Object) */ public final T single(T defaultValue) { Iterator it = iterator(); if (it.hasNext()) { T v = it.next(); if (it.hasNext()) { throw new IndexOutOfBoundsException("The source has more than one element."); } return v; } return defaultValue; } /** * Iterates over this instance, dropping all values it produces. * @see #run() */ public final void subscribe() { run(); } /** * Iterates over this sequence and calls the given onNext action with * each element. * @param onNext the consumer to call with each element * @throws NullPointerException if consumer is null * @since 1.0 */ public final void subscribe(IxConsumer onNext) { for (T v : this) { onNext.accept(v); } } /** * Iterates over this sequence and calls the given onNext action with * each element and calls the onError with any exception thrown by the iteration * or the onNext action. * @param onNext the consumer to call with each element * @param onError the consumer to call with the exception thrown * @throws NullPointerException if onError is null * @since 1.0 */ public final void subscribe(IxConsumer onNext, IxConsumer onError) { try { for (T v : this) { onNext.accept(v); } } catch (Throwable ex) { onError.accept(ex); } } /** * Iterates over this sequence and calls the given onNext action with * each element and calls the onError with any exception thrown by the iteration * or the onNext action; otherwise calls the onCompleted action when the sequence completes * without exception. * @param onNext the consumer to call with each element * @param onError the consumer to call with the exception thrown * @param onCompleted the action called after the sequence has been consumed * @throws NullPointerException if onError or onCompleted is null * @since 1.0 */ public final void subscribe(IxConsumer onNext, IxConsumer onError, Runnable onCompleted) { try { for (T v : this) { onNext.accept(v); } } catch (Throwable ex) { onError.accept(ex); return; } onCompleted.run(); } /** * Collects the elements of this sequence into an Object array. *

* @return the new Object array instance * @since 1.0 */ public final Object[] toArray() { return toList().toArray(); } /** * Collects the elements of this sequence into a generic array provided. *

* @param the output array type * @param array the target array to fill in or use as a template if not long enough * @return the new generic array instance * @since 1.0 */ public final U[] toArray(U[] array) { return toList().toArray(array); } /** * Collects the elements of this sequence into a List. *

* @return the List instance * @since 1.0 */ public final List toList() { List list = new ArrayList(); return into(list); } /** * Collects the elements of this sequence into a Map where the key is * determined from each element via the keySelector function; duplicates are * overwritten. *

* @param the key type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @return the new Map instance * @throws NullPointerException if keySelector is null * @since 1.0 */ public final Map toMap(IxFunction keySelector) { return this.collectToMap(keySelector).first(); } /** * Collects the elements of this sequence into a Map where the key is * determined from each element via the keySelector function and * the value is derived from the same element via the valueSelector function; duplicates are * overwritten. *

* @param the key type * @param the value type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @param valueSelector the function that receives the current element and returns * a value for it to be used as the Map value * @return the new Map instance * @throws NullPointerException if keySelector or valueSelector is null * @since 1.0 */ public final Map toMap(IxFunction keySelector, IxFunction valueSelector) { return this.collectToMap(keySelector, valueSelector).first(); } /** * Collects the elements of this sequence into a multi-Map where the key is * determined from each element via the keySelector function. *

* @param the key type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @return the new Map instance * @throws NullPointerException if keySelector is null * @since 1.0 */ public final Map> toMultimap(IxFunction keySelector) { return this.collectToMultimap(keySelector).first(); } /** * Collects the elements of this sequence into a multi-Map where the key is * determined from each element via the keySelector function and * the value is derived from the same element via the valueSelector function. *

* @param the key type * @param the value type * @param keySelector the function that receives the current element and returns * a key for it to be used as the Map key. * @param valueSelector the function that receives the current element and returns * a value for it to be used as the Map value * @return the new Map instance * @throws NullPointerException if keySelector or valueSelector is null * @since 1.0 */ public final Map> toMultimap(IxFunction keySelector, IxFunction valueSelector) { return this.collectToMultimap(keySelector, valueSelector).first(); } /** * Collects the elements of this sequence into a Set. *

* @return the new Ix instance * @since 1.0 */ public final Set toSet() { Set list = new HashSet(); return into(list); } // -------------------------------------------------------------------------------------------- // Helper methods // -------------------------------------------------------------------------------------------- /** * Checks if the value is null and if so, throws * a NullPointerException with the given message. * @param the value type * @param value the value to check for null * @param message the message to report in the exception * @return the value */ protected static U nullCheck(U value, String message) { if (value == null) { throw new NullPointerException(message); } return value; } /** * Calls the given callable and rethrows its exception * (as RuntimeException if necessary). * @param the value type * @param callable the callable to call * @return the value returned by the callable */ protected static U checkedCall(Callable callable) { try { return callable.call(); } catch (Throwable ex) { if (ex instanceof RuntimeException) { throw (RuntimeException)ex; } if (ex instanceof Error) { throw (Error)ex; } throw new RuntimeException(ex); } } /** * Checks if the given value is non-negative and returns it; throws * an IllegalArgumentException otherwise. * @param n the number to check * @param name the name of the parameter * @return n */ protected static long nonNegative(long n, String name) { if (n < 0L) { throw new IllegalArgumentException(name + " >= 0 required but it was " + n); } return n; } /** * Checks if the given value is non-negative and returns it; throws * an IllegalArgumentException otherwise. * @param n the number to check * @param name the name of the parameter * @return n */ protected static int nonNegative(int n, String name) { if (n < 0L) { throw new IllegalArgumentException(name + " >= 0 required but it was " + n); } return n; } /** * Checks if the given value is positive and returns it; throws * an IllegalArgumentException otherwise. * @param n the number to check * @param name the name of the parameter * @return n */ protected static int positive(int n, String name) { if (n <= 0L) { throw new IllegalArgumentException(name + " > 0 required but it was " + n); } return n; } }