com.landawn.abacus.util.Iterators 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.
/*
* Copyright (c) 2017, 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.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
import com.landawn.abacus.annotation.Beta;
import com.landawn.abacus.logging.Logger;
import com.landawn.abacus.logging.LoggerFactory;
import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.function.TriFunction;
import com.landawn.abacus.util.stream.Stream;
/**
*
* This is a utility class mostly for {@code Iterator}.
*
*
*
* The methods in this class should only read the input {@code Collection/Array/Iterator} parameters, not modify them.
*
*
* @see com.landawn.abacus.util.N
* @see com.landawn.abacus.util.Iterables
* @see com.landawn.abacus.util.Maps
* @see com.landawn.abacus.util.Strings
*/
public final class Iterators {
private static final Logger logger = LoggerFactory.getLogger(Iterators.class);
private Iterators() {
// Utility class.
}
/**
*
* @param
* @param iter
* @param index
* @return
*/
public static Nullable get(final Iterator iter, long index) {
N.checkArgNotNegative(index, "index");
if (iter == null) {
return Nullable.empty();
}
while (iter.hasNext()) {
if (index-- == 0) {
return Nullable. of(iter.next());
} else {
iter.next();
}
}
return Nullable.empty();
}
/**
*
* @param iter
* @return
*/
public static long count(final Iterator iter) {
if (iter == null) {
return 0;
}
long res = 0;
while (iter.hasNext()) {
iter.next();
res++;
}
return res;
}
/**
*
*
* @param
* @param
* @param iter
* @param predicate
* @return
* @throws E
*/
public static long count(final Iterator iter, final Throwables.Predicate predicate) throws E {
N.checkArgNotNull(predicate, "predicate"); //NOSONAR
if (iter == null) {
return 0;
}
long res = 0;
while (iter.hasNext()) {
if (predicate.test(iter.next())) {
res++;
}
}
return res;
}
/**
*
* @param
* @param e
* @param n
* @return
*/
public static ObjIterator repeat(final T e, final int n) {
N.checkArgument(n >= 0, "'n' can't be negative: %s", n); //NOSONAR
if (n == 0) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private int cnt = n;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public T next() {
if (cnt <= 0) {
throw new NoSuchElementException();
}
cnt--;
return e;
}
};
}
/**
*
* @param
* @param c
* @param n
* @return
*/
public static ObjIterator repeatEach(final Collection c, final int n) {
N.checkArgument(n >= 0, "'n' can't be negative: %s", n);
if (n == 0 || N.isNullOrEmpty(c)) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private Iterator iter = c.iterator();
private T next = null;
private int cnt = 0;
@Override
public boolean hasNext() {
return cnt > 0 || iter.hasNext();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
if (cnt <= 0) {
next = iter.next();
cnt = n;
}
cnt--;
return next;
}
};
}
/**
*
* @param
* @param c
* @param n
* @return
*/
public static ObjIterator repeatAll(final Collection c, final int n) {
N.checkArgument(n >= 0, "'n' can't be negative: %s", n);
if (n == 0 || N.isNullOrEmpty(c)) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private Iterator iter = null;
private int cnt = n;
@Override
public boolean hasNext() {
return cnt > 0 || (iter != null && iter.hasNext());
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
if (iter == null || !iter.hasNext()) {
iter = c.iterator();
cnt--;
}
return iter.next();
}
};
}
/**
* Repeat each to size.
*
* @param
* @param c
* @param size
* @return
*/
public static ObjIterator repeatEachToSize(final Collection c, final int size) {
N.checkArgument(size >= 0, "'size' can't be negative: %s", size);
N.checkArgument(size == 0 || N.notNullOrEmpty(c), "Collection can't be empty or null when size > 0");
if (N.isNullOrEmpty(c) || size == 0) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private final int n = size / c.size();
private int mod = size % c.size();
private Iterator iter = null;
private T next = null;
private int cnt = mod-- > 0 ? n + 1 : n;
@Override
public boolean hasNext() {
return cnt > 0 || ((n > 0 || mod > 0) && (iter != null && iter.hasNext()));
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
if (iter == null) {
iter = c.iterator();
next = iter.next();
} else if (cnt <= 0) {
next = iter.next();
cnt = mod-- > 0 ? n + 1 : n;
}
cnt--;
return next;
}
};
}
/**
* Repeat all to size.
*
* @param
* @param c
* @param size
* @return
*/
public static ObjIterator repeatAllToSize(final Collection c, final int size) {
N.checkArgument(size >= 0, "'size' can't be negative: %s", size);
N.checkArgument(size == 0 || N.notNullOrEmpty(c), "Collection can't be empty or null when size > 0");
if (N.isNullOrEmpty(c) || size == 0) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private Iterator iter = null;
private int cnt = size;
@Override
public boolean hasNext() {
return cnt > 0;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
if (iter == null || !iter.hasNext()) {
iter = c.iterator();
}
cnt--;
return iter.next();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static BooleanIterator concat(final boolean[]... a) {
if (N.isNullOrEmpty(a)) {
return BooleanIterator.EMPTY;
}
return new BooleanIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private boolean[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public boolean nextBoolean() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static ShortIterator concat(final short[]... a) {
if (N.isNullOrEmpty(a)) {
return ShortIterator.EMPTY;
}
return new ShortIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private short[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public short nextShort() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static ByteIterator concat(final byte[]... a) {
if (N.isNullOrEmpty(a)) {
return ByteIterator.EMPTY;
}
return new ByteIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private byte[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public byte nextByte() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static IntIterator concat(final int[]... a) {
if (N.isNullOrEmpty(a)) {
return IntIterator.EMPTY;
}
return new IntIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private int[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public int nextInt() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static LongIterator concat(final long[]... a) {
if (N.isNullOrEmpty(a)) {
return LongIterator.EMPTY;
}
return new LongIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private long[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public long nextLong() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static FloatIterator concat(final float[]... a) {
if (N.isNullOrEmpty(a)) {
return FloatIterator.EMPTY;
}
return new FloatIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private float[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public float nextFloat() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static DoubleIterator concat(final double[]... a) {
if (N.isNullOrEmpty(a)) {
return DoubleIterator.EMPTY;
}
return new DoubleIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private double[] cur;
private int cursor = 0;
@Override
public boolean hasNext() {
while ((N.isNullOrEmpty(cur) || cursor >= cur.length) && iter.hasNext()) {
cur = iter.next();
cursor = 0;
}
return cur != null && cursor < cur.length;
}
@Override
public double nextDouble() {
if ((cur == null || cursor >= cur.length) && !hasNext()) {
throw new NoSuchElementException();
}
return cur[cursor++];
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static BooleanIterator concat(final BooleanIterator... a) {
if (N.isNullOrEmpty(a)) {
return BooleanIterator.EMPTY;
}
return new BooleanIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private BooleanIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public boolean nextBoolean() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextBoolean();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static CharIterator concat(final CharIterator... a) {
if (N.isNullOrEmpty(a)) {
return CharIterator.EMPTY;
}
return new CharIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private CharIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public char nextChar() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextChar();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static ByteIterator concat(final ByteIterator... a) {
if (N.isNullOrEmpty(a)) {
return ByteIterator.EMPTY;
}
return new ByteIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private ByteIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public byte nextByte() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextByte();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static ShortIterator concat(final ShortIterator... a) {
if (N.isNullOrEmpty(a)) {
return ShortIterator.EMPTY;
}
return new ShortIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private ShortIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public short nextShort() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextShort();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static IntIterator concat(final IntIterator... a) {
if (N.isNullOrEmpty(a)) {
return IntIterator.EMPTY;
}
return new IntIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private IntIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public int nextInt() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextInt();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static LongIterator concat(final LongIterator... a) {
if (N.isNullOrEmpty(a)) {
return LongIterator.EMPTY;
}
return new LongIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private LongIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public long nextLong() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextLong();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static FloatIterator concat(final FloatIterator... a) {
if (N.isNullOrEmpty(a)) {
return FloatIterator.EMPTY;
}
return new FloatIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private FloatIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public float nextFloat() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextFloat();
}
};
}
/**
*
* @param a
* @return
*/
@SafeVarargs
public static DoubleIterator concat(final DoubleIterator... a) {
if (N.isNullOrEmpty(a)) {
return DoubleIterator.EMPTY;
}
return new DoubleIterator() {
private final Iterator iter = Arrays.asList(a).iterator();
private DoubleIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public double nextDouble() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.nextDouble();
}
};
}
/**
*
* @param
* @param a
* @return
*/
@SafeVarargs
public static ObjIterator concat(final T[]... a) {
if (N.isNullOrEmpty(a)) {
return ObjIterator.empty();
}
final List> list = new ArrayList<>(a.length);
for (T[] e : a) {
if (N.notNullOrEmpty(e)) {
list.add(ObjIterator.of(e));
}
}
return concat(list);
}
/**
*
* @param
* @param a
* @return
*/
@SafeVarargs
public static ObjIterator concat(final Iterator... a) {
if (N.isNullOrEmpty(a)) {
return ObjIterator.empty();
}
return concat(Array.asList(a));
}
/**
*
* @param
* @param a
* @return
*/
@SafeVarargs
public static ObjIterator concat(final Iterable... a) {
if (N.isNullOrEmpty(a)) {
return ObjIterator.empty();
}
final List> list = new ArrayList<>(a.length);
for (Iterable e : a) {
list.add(N.iterate(e));
}
return concat(list);
}
/**
*
*
* @param
* @param
* @param a
* @return
*/
@SafeVarargs
public static ObjIterator> concat(final Map... a) {
if (N.isNullOrEmpty(a)) {
return ObjIterator.empty();
}
final List>> list = new ArrayList<>(a.length);
for (Map e : a) {
if (N.notNullOrEmpty(e)) {
list.add(((Map) e).entrySet().iterator());
}
}
return concat(list);
}
/**
*
* @param
* @param c
* @return
*/
public static ObjIterator concat(final Collection> c) {
if (N.isNullOrEmpty(c)) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private final Iterator> iter = c.iterator();
private Iterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public T next() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.next();
}
};
}
/**
*
* @param
* @param c
* @return
*/
public static ObjIterator concatIterables(final Collection> c) {
if (N.isNullOrEmpty(c)) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private final Iterator> iter = c.iterator();
private Iterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = N.iterate(iter.next());
}
return cur != null && cur.hasNext();
}
@Override
public T next() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.next();
}
};
}
/**
*
* @param
* @param
* @param a
* @return
*/
@SafeVarargs
public static BiIterator concat(final BiIterator... a) {
if (N.isNullOrEmpty(a)) {
return BiIterator.empty();
}
return new BiIterator<>() {
private final Iterator> iter = Arrays.asList(a).iterator();
private BiIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public Pair next() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.next();
}
@Override
protected void next(Throwables.BiConsumer action) throws NoSuchElementException, E {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
cur.next(action);
}
@Override
public void forEachRemaining(final Throwables.BiConsumer action) throws E {
while (hasNext()) {
cur.forEachRemaining(action);
}
}
@Override
public ObjIterator map(final BiFunction mapper) {
N.checkArgNotNull(mapper);
return new ObjIterator<>() {
private ObjIterator mappedIter = null;
@Override
public boolean hasNext() {
if (mappedIter == null || !mappedIter.hasNext()) {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
if (cur != null) {
mappedIter = cur.map(mapper);
}
}
return mappedIter != null && mappedIter.hasNext();
}
@Override
public R next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return mappedIter.next();
}
};
}
};
}
/**
*
* @param
* @param
* @param
* @param a
* @return
*/
@SafeVarargs
public static TriIterator concat(final TriIterator... a) {
if (N.isNullOrEmpty(a)) {
return TriIterator.empty();
}
return new TriIterator<>() {
private final Iterator> iter = Arrays.asList(a).iterator();
private TriIterator cur;
@Override
public boolean hasNext() {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public Triple next() {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
return cur.next();
}
@Override
protected void next(final Throwables.TriConsumer action)
throws NoSuchElementException, E {
if ((cur == null || !cur.hasNext()) && !hasNext()) {
throw new NoSuchElementException();
}
cur.next(action);
}
@Override
public void forEachRemaining(final Throwables.TriConsumer action) throws E {
while (hasNext()) {
cur.forEachRemaining(action);
}
}
@Override
public ObjIterator map(final TriFunction mapper) {
N.checkArgNotNull(mapper);
return new ObjIterator<>() {
private ObjIterator mappedIter = null;
@Override
public boolean hasNext() {
if (mappedIter == null || !mappedIter.hasNext()) {
while ((cur == null || !cur.hasNext()) && iter.hasNext()) {
cur = iter.next();
}
if (cur != null) {
mappedIter = cur.map(mapper);
}
}
return mappedIter != null && mappedIter.hasNext();
}
@Override
public R next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return mappedIter.next();
}
};
}
};
}
/**
*
* @param
* @param a
* @param b
* @param nextSelector
* @return
*/
public static ObjIterator merge(final Iterator a, final Iterator b,
final BiFunction nextSelector) {
N.checkArgNotNull(nextSelector);
return new ObjIterator<>() {
private final Iterator iterA = a == null ? ObjIterator. empty() : a;
private final Iterator iterB = b == null ? ObjIterator. empty() : b;
private T nextA = null;
private T nextB = null;
private boolean hasNextA = false;
private boolean hasNextB = false;
@Override
public boolean hasNext() {
return hasNextA || hasNextB || iterA.hasNext() || iterB.hasNext();
}
@Override
public T next() {
if (hasNextA) {
if (iterB.hasNext()) {
if (nextSelector.apply(nextA, (nextB = iterB.next())) == MergeResult.TAKE_FIRST) {
hasNextA = false;
hasNextB = true;
return nextA;
} else {
return nextB;
}
} else {
hasNextA = false;
return nextA;
}
} else if (hasNextB) {
if (iterA.hasNext()) {
if (nextSelector.apply((nextA = iterA.next()), nextB) == MergeResult.TAKE_FIRST) {
return nextA;
} else {
hasNextA = true;
hasNextB = false;
return nextB;
}
} else {
hasNextB = false;
return nextB;
}
} else if (iterA.hasNext()) {
if (iterB.hasNext()) {
if (nextSelector.apply((nextA = iterA.next()), (nextB = iterB.next())) == MergeResult.TAKE_FIRST) {
hasNextB = true;
return nextA;
} else {
hasNextA = true;
return nextB;
}
} else {
return iterA.next();
}
} else {
return iterB.next();
}
}
};
}
/**
*
*
* @param
* @param c
* @param nextSelector first parameter is selected if Nth.FIRST
is returned, otherwise the second parameter is selected.
* @return
*/
public static ObjIterator merge(final Collection> c,
final BiFunction nextSelector) {
N.checkArgNotNull(nextSelector);
if (N.isNullOrEmpty(c)) {
return ObjIterator. empty();
} else if (c.size() == 1) {
return ObjIterator. of(c.iterator().next());
} else if (c.size() == 2) {
final Iterator> iter = c.iterator();
return merge(iter.next(), iter.next(), nextSelector);
}
final Iterator> iter = c.iterator();
ObjIterator result = merge(iter.next(), iter.next(), nextSelector);
while (iter.hasNext()) {
result = merge(result, iter.next(), nextSelector);
}
return result;
}
/**
*
* @param
* @param a
* @param b
* @param nextSelector
* @return
*/
public static ObjIterator merge(final Iterable a, final Iterable b,
final BiFunction nextSelector) {
final Iterator iterA = N.iterate(a);
final Iterator iterB = N.iterate(b);
return merge(iterA, iterB, nextSelector);
}
// /**
// *
// * @param
// * @param collections
// * @param nextSelector
// * @return
// * @deprecated replaced by {@link #mergeIterables(Collection, BiFunction)}
// */
// @Deprecated
// public static ObjIterator mergeCollections(final Collection> collections,
// final BiFunction nextSelector) {
// return mergeIterables(collections, nextSelector);
// }
/**
*
*
* @param
* @param iterables
* @param nextSelector
* @return
*/
public static ObjIterator mergeIterables(final Collection> iterables,
final BiFunction nextSelector) {
N.checkArgNotNull(nextSelector);
if (N.isNullOrEmpty(iterables)) {
return ObjIterator. empty();
} else if (iterables.size() == 1) {
return ObjIterator. of(iterables.iterator().next());
} else if (iterables.size() == 2) {
final Iterator> iter = iterables.iterator();
return merge(iter.next(), iter.next(), nextSelector);
}
final List> iterList = new ArrayList<>(iterables.size());
for (Iterable e : iterables) {
iterList.add(N.iterate(e));
}
return merge(iterList, nextSelector);
}
/**
*
* @param
* @param a should be in non-descending order as this method does not sort its input.
* @param b should be in non-descending order as this method does not sort its input.
* @return
*/
@SuppressWarnings("rawtypes")
public static ObjIterator mergeSorted(final Iterator a, final Iterator b) {
return mergeSorted(a, b, Comparators. naturalOrder());
}
/**
*
* @param
* @param a should be in non-descending order as this method does not sort its input.
* @param b should be in non-descending order as this method does not sort its input.
* @param cmp
* @return
*/
public static ObjIterator mergeSorted(final Iterator a, final Iterator b, final Comparator cmp) {
N.checkArgNotNull(cmp);
return merge(a, b, MergeResult.minFirst(cmp));
}
/**
*
* @param
* @param a should be in non-descending order as this method does not sort its input.
* @param b should be in non-descending order as this method does not sort its input.
* @return
*/
@SuppressWarnings("rawtypes")
public static ObjIterator mergeSorted(final Iterable a, final Iterable b) {
return mergeSorted(a, b, Comparators. naturalOrder());
}
/**
*
* @param
* @param a should be in non-descending order as this method does not sort its input.
* @param b should be in non-descending order as this method does not sort its input.
* @param cmp
* @return
*/
public static ObjIterator mergeSorted(final Iterable a, final Iterable b, final Comparator cmp) {
final Iterator iterA = N.iterate(a);
final Iterator iterB = N.iterate(b);
return mergeSorted(iterA, iterB, cmp);
}
/**
*
* @param
* @param
* @param
* @param a
* @param b
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterable a, final Iterable b, final BiFunction zipFunction) {
final Iterator iterA = N.iterate(a);
final Iterator iterB = N.iterate(b);
return zip(iterA, iterB, zipFunction);
}
/**
*
* @param
* @param
* @param
* @param a
* @param b
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterator a, final Iterator b, final BiFunction zipFunction) {
N.checkArgNotNull(zipFunction);
return new ObjIterator<>() {
private final Iterator iterA = a == null ? ObjIterator. empty() : a;
private final Iterator iterB = b == null ? ObjIterator. empty() : b;
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext();
}
@Override
public R next() {
return zipFunction.apply(iterA.next(), iterB.next());
}
};
}
/**
*
* @param
* @param
* @param
* @param
* @param a
* @param b
* @param c
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterable a, final Iterable b, final Iterable c,
final TriFunction zipFunction) {
final Iterator iterA = N.iterate(a);
final Iterator iterB = N.iterate(b);
final Iterator iterC = N.iterate(c);
return zip(iterA, iterB, iterC, zipFunction);
}
/**
*
* @param
* @param
* @param
* @param
* @param a
* @param b
* @param c
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterator a, final Iterator b, final Iterator c,
final TriFunction zipFunction) {
N.checkArgNotNull(zipFunction);
return new ObjIterator<>() {
private final Iterator iterA = a == null ? ObjIterator. empty() : a;
private final Iterator iterB = b == null ? ObjIterator. empty() : b;
private final Iterator iterC = c == null ? ObjIterator. empty() : c;
@Override
public boolean hasNext() {
return iterA.hasNext() && iterB.hasNext() && iterC.hasNext();
}
@Override
public R next() {
return zipFunction.apply(iterA.next(), iterB.next(), iterC.next());
}
};
}
/**
*
* @param
* @param
* @param
* @param a
* @param b
* @param valueForNoneA
* @param valueForNoneB
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterable a, final Iterable b, final A valueForNoneA, final B valueForNoneB,
final BiFunction zipFunction) {
final Iterator iterA = N.iterate(a);
final Iterator iterB = N.iterate(b);
return zip(iterA, iterB, valueForNoneA, valueForNoneB, zipFunction);
}
/**
*
* @param
* @param
* @param
* @param a
* @param b
* @param valueForNoneA
* @param valueForNoneB
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB,
final BiFunction zipFunction) {
N.checkArgNotNull(zipFunction);
return new ObjIterator<>() {
private final Iterator iterA = a == null ? ObjIterator. empty() : a;
private final Iterator iterB = b == null ? ObjIterator. empty() : b;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext();
}
@Override
public R next() {
if (iterA.hasNext()) {
return zipFunction.apply(iterA.next(), iterB.hasNext() ? iterB.next() : valueForNoneB);
} else {
return zipFunction.apply(valueForNoneA, iterB.next());
}
}
};
}
/**
*
* @param
* @param
* @param
* @param
* @param a
* @param b
* @param c
* @param valueForNoneA
* @param valueForNoneB
* @param valueForNoneC
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterable a, final Iterable b, final Iterable c, final A valueForNoneA, final B valueForNoneB,
final C valueForNoneC, final TriFunction zipFunction) {
final Iterator iterA = N.iterate(a);
final Iterator iterB = N.iterate(b);
final Iterator iterC = N.iterate(c);
return zip(iterA, iterB, iterC, valueForNoneA, valueForNoneB, valueForNoneC, zipFunction);
}
/**
*
* @param
* @param
* @param
* @param
* @param a
* @param b
* @param c
* @param valueForNoneA
* @param valueForNoneB
* @param valueForNoneC
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA, final B valueForNoneB,
final C valueForNoneC, final TriFunction zipFunction) {
return new ObjIterator<>() {
private final Iterator iterA = a == null ? ObjIterator. empty() : a;
private final Iterator iterB = b == null ? ObjIterator. empty() : b;
private final Iterator iterC = c == null ? ObjIterator. empty() : c;
@Override
public boolean hasNext() {
return iterA.hasNext() || iterB.hasNext() || iterC.hasNext();
}
@Override
public R next() {
if (iterA.hasNext()) {
return zipFunction.apply(iterA.next(), iterB.hasNext() ? iterB.next() : valueForNoneB, iterC.hasNext() ? iterC.next() : valueForNoneC);
} else if (iterB.hasNext()) {
return zipFunction.apply(valueForNoneA, iterB.next(), iterC.hasNext() ? iterC.next() : valueForNoneC);
} else {
return zipFunction.apply(valueForNoneA, valueForNoneB, iterC.next());
}
}
};
}
/**
*
* @param
* @param
* @param
* @param iter
* @param unzip the second parameter is an output parameter.
* @return
* @see BiIterator#unzip(Iterator, BiConsumer)
*/
public static BiIterator unzip(final Iterator iter, final BiConsumer> unzip) {
return BiIterator.unzip(iter, unzip);
}
/**
*
* @param
* @param
* @param
* @param c
* @param unzip the second parameter is an output parameter.
* @return
* @see BiIterator#unzip(Iterable, BiConsumer)
*/
public static BiIterator unzip(final Iterable c, final BiConsumer> unzip) {
return BiIterator.unzip(N.iterate(c), unzip);
}
/**
*
* @param
* @param
* @param
* @param
* @param iter
* @param unzip the second parameter is an output parameter.
* @return
* @see TriIterator#unzip(Iterator, BiConsumer)
*/
@Beta
public static TriIterator unzipp(final Iterator iter, final BiConsumer> unzip) {
return TriIterator.unzip(iter, unzip);
}
/**
*
* @param
* @param
* @param
* @param
* @param c
* @param unzip the second parameter is an output parameter.
* @return
* @see TriIterator#unzip(Iterable, BiConsumer)
*/
@Beta
public static TriIterator unzipp(final Iterable c, final BiConsumer> unzip) {
return TriIterator.unzip(N.iterate(c), unzip);
}
/**
* Note: copied from Google Guava under Apache license v2
*
* Calls {@code next()} on {@code iterator}, either {@code numberToAdvance} times
* or until {@code hasNext()} returns {@code false}, whichever comes first.
*
* @param iterator
* @param numberToAdvance
* @return
*/
public static long advance(Iterator iterator, long numberToAdvance) {
N.checkArgNotNegative(numberToAdvance, "numberToAdvance");
long i;
for (i = 0; i < numberToAdvance && iterator.hasNext(); i++) {
iterator.next();
}
return i;
}
/**
* Calls {@code next()} on {@code iterator}, either {@code n} times
* or until {@code hasNext()} returns {@code false}, whichever comes first.
*
* This is a lazy evaluation operation. The {@code skip} action is only triggered when {@code Iterator.hasNext()} or {@code Iterator.next()} is called.
*
* @param
* @param iter
* @param n
* @return
*/
public static ObjIterator skip(final Iterator iter, final long n) {
N.checkArgNotNegative(n, "n");
if (iter == null) {
return ObjIterator.empty();
} else if (n <= 0) {
return ObjIterator.of(iter);
}
return new ObjIterator<>() {
private boolean skipped = false;
@Override
public boolean hasNext() {
if (!skipped) {
skip();
}
return iter.hasNext();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return iter.next();
}
private void skip() {
long idx = 0;
while (idx++ < n && iter.hasNext()) {
iter.next();
}
skipped = true;
}
};
}
/**
* Returns a new {@code Iterator}.
*
* @param
* @param iter
* @param count
* @return
*/
public static ObjIterator limit(final Iterator iter, final long count) {
N.checkArgNotNegative(count, "count");
if (iter == null || count == 0) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private long cnt = count;
@Override
public boolean hasNext() {
return cnt > 0 && iter.hasNext();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
cnt--;
return iter.next();
}
};
}
/**
* Calls {@code next()} on {@code iterator}, either {@code offset} times
* or until {@code hasNext()} returns {@code false}, whichever comes first.
*
* This is a lazy evaluation operation. The {@code skip} action is only triggered when {@code Iterator.hasNext()} or {@code Iterator.next()} is called.
*
*
* @param
* @param iter
* @param offset
* @param count
* @return
*/
public static ObjIterator skipAndLimit(final Iterator iter, final long offset, final long count) {
N.checkArgNotNegative(count, "offset");
N.checkArgNotNegative(count, "count");
if (iter == null) {
return ObjIterator.empty();
}
return new ObjIterator<>() {
private long cnt = count;
private boolean skipped = false;
@Override
public boolean hasNext() {
if (!skipped) {
skip();
}
return cnt > 0 && iter.hasNext();
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
cnt--;
return iter.next();
}
private void skip() {
long idx = 0;
while (idx++ < offset && iter.hasNext()) {
iter.next();
}
skipped = true;
}
};
}
/**
* Returns a new {@code ObjIterator} with {@code null} elements removed.
*
* @param
* @param iter
* @return
* @deprecated Use {@link #skipNulls(Iterator)} instead
*/
@Deprecated
public static ObjIterator skipNull(final Iterator iter) {
return skipNulls(iter);
}
/**
* Returns a new {@code ObjIterator} with {@code null} elements removed.
*
* @param
* @param iter
* @return
*/
public static ObjIterator skipNulls(final Iterator iter) {
return filter(iter, Fn. notNull());
}
/**
*
*
* @param
* @param iter
* @return
*/
public static ObjIterator distinct(final Iterator iter) {
if (iter == null) {
return ObjIterator.empty();
}
final Set set = new HashSet<>();
return new ObjIterator<>() {
private final T NONE = (T) N.NULL_MASK; //NOSONAR
private T next = NONE;
private T tmp = null;
@Override
public boolean hasNext() {
if (next == NONE) {
while (iter.hasNext()) {
tmp = iter.next();
if (set.add(tmp)) {
next = tmp;
break;
}
}
}
return next != NONE;
}
@Override
public T next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
tmp = next;
next = NONE;
return tmp;
}
};
}
/**
*
*
* @param
* @param iter
* @param keyMapper
* @return
*/
public static