com.landawn.abacus.util.TriIterator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of abacus-common Show documentation
Show all versions of abacus-common Show documentation
A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.
The newest version!
/*
* Copyright (c) 2018, Haiyang Li.
*
* 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 com.landawn.abacus.util;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.landawn.abacus.util.Fn.Suppliers;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.function.IntObjConsumer;
import com.landawn.abacus.util.function.TriConsumer;
import com.landawn.abacus.util.function.TriFunction;
import com.landawn.abacus.util.function.TriPredicate;
import com.landawn.abacus.util.stream.Stream;
/**
* The TriIterator class is an abstract class that extends ImmutableIterator.
* It represents an iterator over a triple of values of type A, B, and C.
* This class provides a blueprint for classes that need to implement a tri-directional iterator.
*
* @param the first type of elements returned by this iterator
* @param the second type of elements returned by this iterator
* @param the third type of elements returned by this iterator
*
* @see com.landawn.abacus.util.Iterators
* @see com.landawn.abacus.util.Enumerations
*
*/
@SuppressWarnings({ "java:S6548" })
public abstract class TriIterator extends ImmutableIterator> {
@SuppressWarnings("rawtypes")
private static final TriIterator EMPTY = new TriIterator() {
@Override
public boolean hasNext() {
return false;
}
@Override
public Object next() {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
@Override
protected void next(final Throwables.TriConsumer action) throws NoSuchElementException {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
@Override
public void forEachRemaining(final TriConsumer action) throws IllegalArgumentException {
N.checkArgNotNull(action);
}
@Override
public void foreachRemaining(final Throwables.TriConsumer action) throws IllegalArgumentException {
N.checkArgNotNull(action);
}
@Override
public ObjIterator map(final TriFunction mapper) throws IllegalArgumentException {
N.checkArgNotNull(mapper, cs.mapper);
return ObjIterator.empty();
}
};
/**
* Returns an empty TriIterator.
*
* @param the first type of elements returned by this iterator
* @param the second type of elements returned by this iterator
* @param the third type of elements returned by this iterator
* @return an empty TriIterator
*/
public static TriIterator empty() {
return EMPTY;
}
/**
* Generates an infinite {@code TriIterator} instance with the provided output Consumer.
* The output Consumer is responsible for producing the next Triple on each iteration.
*
* @param the first type of elements returned by this iterator
* @param the second type of elements returned by this iterator
* @param the third type of elements returned by this iterator
* @param output A Consumer that accepts a Triple and produces the next Triple on each iteration.
* @return A TriIterator that uses the provided output Consumer to generate its elements.
* @see #generate(BooleanSupplier, Consumer)
*/
public static TriIterator generate(final Consumer> output) {
return generate(com.landawn.abacus.util.function.BooleanSupplier.TRUE, output);
}
/**
* Generates a TriIterator instance with the provided hasNext BooleanSupplier and output Consumer.
* The hasNext BooleanSupplier is used to determine if the iterator has more elements.
* The output Consumer is responsible for producing the next Triple on each iteration.
*
* @param the first type of elements returned by this iterator
* @param the second type of elements returned by this iterator
* @param the third type of elements returned by this iterator
* @param hasNext A BooleanSupplier that returns {@code true} if the iterator has more elements.
* @param output A Consumer that accepts a Triple and produces the next Triple on each iteration.
* @return A TriIterator that uses the provided hasNext BooleanSupplier and output Consumer to generate its elements.
* @throws IllegalArgumentException If hasNext or output is {@code null}.
*/
public static TriIterator generate(final BooleanSupplier hasNext, final Consumer> output)
throws IllegalArgumentException {
N.checkArgNotNull(hasNext);
N.checkArgNotNull(output);
return new TriIterator<>() {
private final Triple tmp = new Triple<>();
@Override
public boolean hasNext() {
return hasNext.getAsBoolean();
}
@Override
public Triple next() throws IllegalArgumentException {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
output.accept(tmp);
return Triple.of(tmp.left, tmp.middle, tmp.right);
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
// N.checkArgNotNull(action);
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
output.accept(tmp);
action.accept(tmp.left, tmp.middle, tmp.right);
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) throws IllegalArgumentException {
N.checkArgNotNull(action);
while (hasNext.getAsBoolean()) {
output.accept(tmp);
action.accept(tmp.left, tmp.middle, tmp.right);
}
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws IllegalArgumentException, E {
N.checkArgNotNull(action);
while (hasNext.getAsBoolean()) {
output.accept(tmp);
action.accept(tmp.left, tmp.middle, tmp.right);
}
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) throws IllegalArgumentException {
N.checkArgNotNull(mapper);
return new ObjIterator<>() {
@Override
public boolean hasNext() {
return hasNext.getAsBoolean();
}
@Override
public R next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
output.accept(tmp);
return mapper.apply(tmp.left, tmp.middle, tmp.right);
}
};
}
};
}
/**
* Generates a TriIterator instance with the provided fromIndex, toIndex, and output IntObjConsumer.
* The fromIndex and toIndex define the size of the returned iterator.
* The output IntObjConsumer is responsible for producing the next Triple on each iteration.
*
* @param the first type of elements returned by this iterator
* @param the second type of elements returned by this iterator
* @param the third type of elements returned by this iterator
* @param fromIndex The starting index of the iterator.
* @param toIndex The ending index of the iterator.
* @param output An IntObjConsumer that accepts an integer and a Triple and produces the next Triple on each iteration.
* @return A TriIterator that uses the provided fromIndex, toIndex, and output IntObjConsumer to generate its elements.
* @throws IllegalArgumentException If fromIndex is greater than toIndex.
* @throws IndexOutOfBoundsException If fromIndex or toIndex is out of range.
*/
public static TriIterator generate(final int fromIndex, final int toIndex, final IntObjConsumer> output)
throws IllegalArgumentException, IndexOutOfBoundsException {
N.checkFromToIndex(fromIndex, toIndex, Integer.MAX_VALUE);
N.checkArgNotNull(output);
return new TriIterator<>() {
private final MutableInt cursor = MutableInt.of(fromIndex);
private final Triple tmp = new Triple<>();
@Override
public boolean hasNext() {
return cursor.value() < toIndex;
}
@Override
public Triple next() throws IllegalArgumentException {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
output.accept(cursor.getAndIncrement(), tmp);
return Triple.of(tmp.left, tmp.middle, tmp.right);
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
// N.checkArgNotNull(action);
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
output.accept(cursor.getAndIncrement(), tmp);
action.accept(tmp.left, tmp.middle, tmp.right);
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) throws IllegalArgumentException {
N.checkArgNotNull(action);
while (cursor.value() < toIndex) {
output.accept(cursor.getAndIncrement(), tmp);
action.accept(tmp.left, tmp.middle, tmp.right);
}
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws IllegalArgumentException, E {
N.checkArgNotNull(action);
while (cursor.value() < toIndex) {
output.accept(cursor.getAndIncrement(), tmp);
action.accept(tmp.left, tmp.middle, tmp.right);
}
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) throws IllegalArgumentException {
N.checkArgNotNull(mapper);
return new ObjIterator<>() {
@Override
public boolean hasNext() {
return cursor.value() < toIndex;
}
@Override
public R next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
output.accept(cursor.getAndIncrement(), tmp);
return mapper.apply(tmp.left, tmp.middle, tmp.right);
}
};
}
};
}
/**
* Zips three arrays into a TriIterator.
* The resulting TriIterator will iterate over triples of elements from the three arrays.
* If the arrays have different lengths, the resulting TriIterator will have the length of the shortest array.
* If any of arrays is {@code null}, returns an empty TriIterator.
*
* @param the type of elements in the first array
* @param the type of elements in the second array
* @param the type of elements in the third array
* @param a the first array
* @param b the second array
* @param c the third array
* @return a TriIterator that iterates over the elements of the three arrays in parallel
*/
public static TriIterator zip(final A[] a, final B[] b, final C[] c) {
return zip(Array.asList(a), Array.asList(b), Array.asList(c));
}
/**
* Zips three arrays into a TriIterator with specified default values for missing elements.
* The resulting TriIterator will iterate over triples of elements from the three arrays.
* If the arrays have different lengths, the resulting TriIterator will continue with the default values
* for the shorter array until the longest array is exhausted.
*
* @param the type of elements in the first array
* @param the type of elements in the second array
* @param the type of elements in the third array
* @param a the first array
* @param b the second array
* @param c the third array
* @param valueForNoneA the default value for missing elements in the first array
* @param valueForNoneB the default value for missing elements in the second array
* @param valueForNoneC the default value for missing elements in the third array
* @return a TriIterator that iterates over the elements of the three arrays in parallel, using default values for missing elements
*/
public static TriIterator zip(final A[] a, final B[] b, final C[] c, final A valueForNoneA, final B valueForNoneB,
final C valueForNoneC) {
return zip(Array.asList(a), Array.asList(b), Array.asList(c), valueForNoneA, valueForNoneB, valueForNoneC);
}
/**
* Zips three iterables into a TriIterator.
* The resulting TriIterator will iterate over triples of elements from the three iterables.
* If the iterables have different lengths, the resulting TriIterator will have the length of the shortest iterable.
* If any of iterable is {@code null}, returns an empty TriIterator.
*
* @param the type of elements in the first iterable
* @param the type of elements in the second iterable
* @param the type of elements in the third iterable
* @param a the first iterable
* @param b the second iterable
* @param c the third iterable
* @return a TriIterator that iterates over the elements of the three iterables in parallel
*/
public static TriIterator zip(final Iterable a, final Iterable b, final Iterable c) {
return zip(a == null ? null : a.iterator(), b == null ? null : b.iterator(), c == null ? null : c.iterator());
}
/**
* Zips three iterables into a TriIterator with specified default values for missing elements.
* The resulting TriIterator will iterate over triples of elements from the three iterables.
* If the iterables have different lengths, the resulting TriIterator will continue with the default values
* for the shorter iterable until the longest iterable is exhausted.
*
* @param the type of elements in the first iterable
* @param the type of elements in the second iterable
* @param the type of elements in the third iterable
* @param a the first iterable
* @param b the second iterable
* @param c the third iterable
* @param valueForNoneA the default value for missing elements in the first iterable
* @param valueForNoneB the default value for missing elements in the second iterable
* @param valueForNoneC the default value for missing elements in the third iterable
* @return a TriIterator that iterates over the elements of the three iterables in parallel, using default values for missing elements
*/
public static TriIterator zip(final Iterable a, final Iterable b, final Iterable c, final A valueForNoneA,
final B valueForNoneB, final C valueForNoneC) {
return zip(a == null ? null : a.iterator(), b == null ? null : b.iterator(), c == null ? null : c.iterator(), valueForNoneA, valueForNoneB,
valueForNoneC);
}
/**
* Zips three iterators into a TriIterator.
* The resulting TriIterator will iterate over triples of elements from the three iterators.
* If the iterators have different lengths, the resulting TriIterator will have the length of the shortest iterator.
* If any of iterator is {@code null}, returns an empty TriIterator.
*
* @param the type of elements in the first iterator
* @param the type of elements in the second iterator
* @param the type of elements in the third iterator
* @param iterA the first iterator
* @param iterB the second iterator
* @param iterC the third iterator
* @return a TriIterator that iterates over the elements of the three iterators in parallel
*/
public static TriIterator zip(final Iterator iterA, final Iterator iterB, final Iterator iterC) {
if (iterA == null || iterB == null || iterC == null) {
return empty();
}
return new TriIterator<>() {
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext() && iterC.hasNext();
}
@Override
public Triple next() throws IllegalArgumentException {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
return Triple.of(iterA.next(), iterB.next(), iterC.next());
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
// N.checkArgNotNull(action);
action.accept(iterA.next(), iterB.next(), iterC.next());
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) throws IllegalArgumentException {
N.checkArgNotNull(action);
while (iterA.hasNext() && iterB.hasNext() && iterC.hasNext()) {
action.accept(iterA.next(), iterB.next(), iterC.next());
}
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws IllegalArgumentException, E {
N.checkArgNotNull(action);
while (iterA.hasNext() && iterB.hasNext() && iterC.hasNext()) {
action.accept(iterA.next(), iterB.next(), iterC.next());
}
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) throws IllegalArgumentException {
N.checkArgNotNull(mapper);
return new ObjIterator<>() {
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext() && iterC.hasNext();
}
@Override
public R next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
return mapper.apply(iterA.next(), iterB.next(), iterC.next());
}
};
}
};
}
/**
* Zips three iterators into a TriIterator with specified default values for missing elements.
* The resulting TriIterator will iterate over triples of elements from the three iterators.
* If the iterators have different lengths, the resulting TriIterator will continue with the default values
* for the shorter iterator until the longest iterator is exhausted.
*
* @param the type of elements in the first iterator
* @param the type of elements in the second iterator
* @param the type of elements in the third iterator
* @param iterA the first iterator
* @param iterB the second iterator
* @param iterC the third iterator
* @param valueForNoneA the default value for missing elements in the first iterator
* @param valueForNoneB the default value for missing elements in the second iterator
* @param valueForNoneC the default value for missing elements in the third iterator
* @return a TriIterator that iterates over the elements of the three iterators in parallel, using default values for missing elements
*/
public static TriIterator zip(final Iterator iterA, final Iterator iterB, final Iterator iterC, final A valueForNoneA,
final B valueForNoneB, final C valueForNoneC) {
final Iterator iter1 = iterA == null ? ObjIterator.empty() : iterA;
final Iterator iter2 = iterB == null ? ObjIterator.empty() : iterB;
final Iterator iter3 = iterC == null ? ObjIterator.empty() : iterC;
return new TriIterator<>() {
@Override
public boolean hasNext() {
return iter1.hasNext() || iter2.hasNext() || iter3.hasNext();
}
@Override
public Triple next() throws IllegalArgumentException {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
return Triple.of(iter1.hasNext() ? iter1.next() : valueForNoneA, iter2.hasNext() ? iter2.next() : valueForNoneB,
iter3.hasNext() ? iter3.next() : valueForNoneC);
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
// N.checkArgNotNull(action);
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
action.accept(iter1.hasNext() ? iter1.next() : valueForNoneA, iter2.hasNext() ? iter2.next() : valueForNoneB,
iter3.hasNext() ? iter3.next() : valueForNoneC);
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) throws IllegalArgumentException {
N.checkArgNotNull(action);
while (iter1.hasNext() || iter2.hasNext() || iter3.hasNext()) {
action.accept(iter1.hasNext() ? iter1.next() : valueForNoneA, iter2.hasNext() ? iter2.next() : valueForNoneB,
iter3.hasNext() ? iter3.next() : valueForNoneC);
}
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws IllegalArgumentException, E {
N.checkArgNotNull(action);
while (iter1.hasNext() || iter2.hasNext() || iter3.hasNext()) {
action.accept(iter1.hasNext() ? iter1.next() : valueForNoneA, iter2.hasNext() ? iter2.next() : valueForNoneB,
iter3.hasNext() ? iter3.next() : valueForNoneC);
}
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) throws IllegalArgumentException {
N.checkArgNotNull(mapper);
return new ObjIterator<>() {
@Override
public boolean hasNext() {
return iter1.hasNext() || iter2.hasNext() || iter3.hasNext();
}
@Override
public R next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
return mapper.apply(iter1.hasNext() ? iter1.next() : valueForNoneA, iter2.hasNext() ? iter2.next() : valueForNoneB,
iter3.hasNext() ? iter3.next() : valueForNoneC);
}
};
}
};
}
/**
* Unzips an iterable of elements into a TriIterator.
* The resulting TriIterator will iterate over triples of elements produced by the unzip function.
* If the iterable is {@code null}, an empty TriIterator is returned.
*
* @param the type of elements in the input iterable
* @param the type of elements in the first component of the triple
* @param the type of elements in the second component of the triple
* @param the type of elements in the third component of the triple
* @param iter the input iterable
* @param unzipFunc a BiConsumer that accepts an element of type T and a {@code Triple} and populates the triple with the unzipped values
* @return a TriIterator that iterates over the unzipped elements
*/
public static TriIterator unzip(final Iterable extends T> iter, final BiConsumer super T, Triple> unzipFunc) {
if (iter == null) {
return TriIterator.empty();
}
return unzip(iter.iterator(), unzipFunc);
}
/**
* Unzips an iterator of elements into a TriIterator.
* The resulting TriIterator will iterate over triples of elements produced by the unzip function.
* If the iterator is {@code null}, an empty TriIterator is returned.
*
* @param the type of elements in the input iterator
* @param the type of elements in the first component of the triple
* @param the type of elements in the second component of the triple
* @param the type of elements in the third component of the triple
* @param iter the input iterator
* @param unzipFunc a BiConsumer that accepts an element of type T and a Triple and populates the triple with the unzipped values
* @return a TriIterator that iterates over the unzipped elements
*/
public static TriIterator unzip(final Iterator extends T> iter, final BiConsumer super T, Triple> unzipFunc) {
if (iter == null) {
return TriIterator.empty();
}
final BooleanSupplier hasNext = iter::hasNext;
final Consumer> output = out -> unzipFunc.accept(iter.next(), out);
return TriIterator.generate(hasNext, output);
}
/**
*
* @param
* @param action
* @throws NoSuchElementException
* @throws E
*/
protected abstract void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E;
/**
* Performs the given action for each remaining element in the iterator until all elements have been processed or the action throws an exception.
*
* @param action the action to be performed for each element
* @deprecated use {@code forEachRemaining(TriConsumer)} to avoid creating the unnecessary {@code Triple} Objects.
* @see #forEachRemaining(TriConsumer)
*/
@Override
@Deprecated
public void forEachRemaining(final Consumer super Triple> action) {
super.forEachRemaining(action);
}
/**
* Performs the given action for each remaining element in the iterator until all elements
* have been processed or the action throws an exception.
*
* @param action the action to be performed for each element
*/
public abstract void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action);
/**
* Performs the given action for each remaining element in the iterator until all elements
* have been processed or the action throws an exception.
*
* @param the type of exception that the action may throw
* @param action the action to be performed for each element
* @throws E if the action throws an exception
*/
public abstract void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action) throws E; // NOSONAR
@SuppressWarnings("rawtypes")
private static final Throwables.TriConsumer DO_NOTHING = (a, b, c) -> {
// do nothing;
};
/**
* Returns a new TriIterator with n elements skipped from the beginning of this TriIterator.
*
* @param n the number of elements to skip
* @return A new TriIterator that skips the first n elements.
* @throws IllegalArgumentException If n is negative.
*/
public TriIterator skip(final long n) throws IllegalArgumentException {
N.checkArgNotNegative(n, cs.n);
if (n <= 0) {
return this;
}
final TriIterator iter = this;
return new TriIterator<>() {
private boolean skipped = false;
@Override
public boolean hasNext() {
if (!skipped) {
skip();
}
return iter.hasNext();
}
@Override
public Triple next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
return iter.next();
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
if (!skipped) {
skip();
}
iter.next(action);
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) {
if (!skipped) {
skip();
}
iter.forEachRemaining(action);
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action) throws E {
if (!skipped) {
skip();
}
iter.foreachRemaining(action);
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) {
N.checkArgNotNull(mapper, cs.mapper);
if (!skipped) {
skip();
}
return iter.map(mapper);
}
private void skip() {
long idx = 0;
while (idx++ < n && iter.hasNext()) {
iter.next(DO_NOTHING);
}
skipped = true;
}
};
}
/**
* Returns a new TriIterator with a limited number of elements.
* The resulting TriIterator will contain at most the specified number of elements.
*
* @param count the maximum number of elements to include in the resulting TriIterator
* @return a new TriIterator that contains at most the specified number of elements
* @throws IllegalArgumentException If count is negative.
*/
public TriIterator limit(final long count) throws IllegalArgumentException {
N.checkArgNotNegative(count, cs.count);
if (count == 0) {
return TriIterator.empty();
}
final TriIterator iter = this;
return new TriIterator<>() {
private long cnt = count;
@Override
public boolean hasNext() {
return cnt > 0 && iter.hasNext();
}
@Override
public Triple next() {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
cnt--;
return iter.next();
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
if (!hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
cnt--;
iter.next(action);
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) {
while (hasNext()) {
cnt--;
iter.next(action);
}
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action) throws E {
while (hasNext()) {
cnt--;
iter.next(action);
}
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) {
N.checkArgNotNull(mapper, cs.mapper);
if (cnt > 0) {
return iter. map(mapper).limit(cnt);
} else {
return ObjIterator.empty();
}
}
};
}
/**
* Returns a new TriIterator that includes only the elements that satisfy the provided predicate.
*
* @param predicate the predicate to apply to each pair of elements
* @return a new TriIterator containing only the elements that match the predicate
*/
public TriIterator filter(final TriPredicate super A, ? super B, ? super C> predicate) {
N.checkArgNotNull(predicate, cs.Predicate);
final TriIterator iter = this;
return new TriIterator<>() {
private final Triple next = new Triple<>();
private final Throwables.TriConsumer setNext = next::set;
private boolean hasNext = false;
@Override
public boolean hasNext() {
if (!hasNext) {
while (iter.hasNext()) {
iter.next(setNext);
if (predicate.test(next.left, next.middle, next.right)) {
hasNext = true;
break;
}
}
}
return hasNext;
}
@Override
public Triple next() {
if (!hasNext && !hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
hasNext = false;
return next.copy();
}
@Override
protected void next(final Throwables.TriConsumer super A, ? super B, ? super C, E> action)
throws NoSuchElementException, E {
if (!hasNext && !hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
hasNext = false;
action.accept(next.left, next.middle, next.right);
}
@Override
public void forEachRemaining(final TriConsumer super A, ? super B, ? super C> action) {
while (hasNext()) {
hasNext = false;
action.accept(next.left, next.middle, next.right);
}
}
@Override
public void foreachRemaining(final Throwables.TriConsumer super A, ? super B, ? super C, E> action) throws E {
while (hasNext()) {
hasNext = false;
action.accept(next.left, next.middle, next.right);
}
}
@Override
public ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) {
N.checkArgNotNull(mapper, cs.mapper);
return new ObjIterator<>() {
@Override
public boolean hasNext() {
if (!hasNext) {
while (iter.hasNext()) {
iter.next(setNext);
if (predicate.test(next.left, next.middle, next.right)) {
hasNext = true;
break;
}
}
}
return hasNext;
}
@Override
public R next() {
if (!hasNext && !hasNext()) {
throw new NoSuchElementException(InternalUtil.ERROR_MSG_FOR_NO_SUCH_EX);
}
hasNext = false;
return mapper.apply(next.left, next.middle, next.right);
}
};
}
};
}
/**
* Transforms the elements of this TriIterator using the given mapper function.
*
* @param the type of elements in the resulting ObjIterator
* @param mapper the function to apply to each triple of elements
* @return an ObjIterator containing the elements produced by the mapper function
*/
public abstract ObjIterator map(final TriFunction super A, ? super B, ? super C, ? extends R> mapper);
/**
* Returns an Optional containing the first triple of elements in the iterator.
* If the iterator is empty, returns an empty Optional.
*
* @return an Optional containing the first triple of elements, or an empty Optional if the iterator is empty
*/
public Optional> first() {
if (hasNext()) {
return Optional.of(next());
} else {
return Optional.empty();
}
}
/**
* Returns an Optional containing the last triple of elements in the iterator.
* If the iterator is empty, returns an empty Optional.
*
* @return an Optional containing the last triple of elements, or an empty Optional if the iterator is empty
*/
public Optional> last() {
if (hasNext()) {
final Triple next = new Triple<>();
final Throwables.TriConsumer setNext = next::set;
foreachRemaining(setNext);
return Optional.of(next);
} else {
return Optional.empty();
}
}
/**
* Returns a Stream of elements produced by applying the given mapper function to each triple of elements in this TriIterator.
*
* @param the type of elements in the resulting Stream
* @param mapper the function to apply to each triple of elements
* @return a Stream containing the elements produced by the mapper function
*/
public Stream stream(final TriFunction super A, ? super B, ? super C, ? extends R> mapper) {
N.checkArgNotNull(mapper, cs.mapper);
return Stream.of(map(mapper));
}
/**
* Converts the elements in this TriIterator to an array of Triple objects.
*
* @return An array containing the remaining triples of elements in this TriIterator.
*/
public Triple[] toArray() {
return toArray(new Triple[0]);
}
/**
* Converts the elements in this TriIterator to an array of the specified type.
*
* @param the type of the array elements. It should be super type of Triple.
* @param a the array into which the elements of this TriIterator are to be stored, if it is big enough;
* otherwise, a new array of the same runtime type is allocated for this purpose.
* @return an array containing the elements of this TriIterator
* @deprecated This method is deprecated. Use {@link #toArray()} or {@link #toList()} instead.
*/
@Deprecated
public T[] toArray(final T[] a) {
return toList().toArray(a);
}
/**
* Converts the elements in this TriIterator to a List of Triple objects.
*
* @return a List containing all triples of elements in this TriIterator
*/
public List> toList() {
return toCollection(Suppliers.ofList());
}
/**
* Converts the elements in this TriIterator to three separate lists of type A, B, and C.
* The resulting Triple contains three lists, each containing the elements of the corresponding type.
*
* @param supplier a Supplier that provides new instances of List for storing the elements
* @return a Triple containing three lists of elements of type A, B, and C
*/
public Triple, List, List> toMultiList(@SuppressWarnings("rawtypes") final Supplier extends List> supplier) {
final List listA = supplier.get();
final List listB = supplier.get();
final List listC = supplier.get();
this.foreachRemaining((a, b, c) -> {
listA.add(a);
listB.add(b);
listC.add(c);
});
return Triple.of(listA, listB, listC);
}
/**
* Converts the elements in this TriIterator to three separate sets of type A, B, and C.
* The resulting Triple contains three sets, each containing the elements of the corresponding type.
*
* @param supplier a Supplier that provides new instances of Set for storing the elements
* @return a Triple containing three sets of elements of type A, B, and C
*/
public Triple, Set, Set> toMultiSet(@SuppressWarnings("rawtypes") final Supplier extends Set> supplier) {
final Set listA = supplier.get();
final Set listB = supplier.get();
final Set listC = supplier.get();
this.foreachRemaining((a, b, c) -> {
listA.add(a);
listB.add(b);
listC.add(c);
});
return Triple.of(listA, listB, listC);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy