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-util-se Show documentation
Show all versions of abacus-util-se 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.HashMap;
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 com.landawn.abacus.exception.DuplicatedResultException;
import com.landawn.abacus.util.u.Nullable;
import com.landawn.abacus.util.u.Optional;
import com.landawn.abacus.util.function.BiConsumer;
import com.landawn.abacus.util.function.BiFunction;
import com.landawn.abacus.util.function.BiPredicate;
import com.landawn.abacus.util.function.Function;
import com.landawn.abacus.util.function.Predicate;
import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.function.TriFunction;
/**
* The methods in this class should only read the input {@code Collections/Arrays}, not modify any of them.
*
* @author Haiyang Li
* @since 0.9
*/
public final class Iterators {
private Iterators() {
// singleton.
}
/**
*
* @param iter
* @param objToFind
* @return true, if successful
*/
public static boolean contains(final Iterator> iter, final Object objToFind) {
if (iter == null) {
return false;
}
while (iter.hasNext()) {
if (N.equals(iter.next(), objToFind)) {
return true;
}
}
return false;
}
/**
*
* @param iter
* @param objToFind
* @return true, if successful
*/
public static boolean containsAny(final Iterator> iter, final Set> objsToFind) {
if (iter == null || N.isNullOrEmpty(objsToFind)) {
return false;
}
while (iter.hasNext()) {
if (objsToFind.contains(iter.next())) {
return true;
}
}
return false;
}
/**
*
* @param iter
* @param objToFind
* @return true, if successful
*/
public static boolean containsAll(final Iterator> iter, final Collection> objsToFind) {
if (N.isNullOrEmpty(objsToFind)) {
return true;
} else if (iter == null) {
return false;
}
final Set> set = new HashSet<>(objsToFind);
while (iter.hasNext()) {
if (set.remove(iter.next())) {
if (set.size() == 0) {
return true;
}
}
}
return false;
}
/**
*
* @param iter
* @param objToFind
* @return
*/
public static long indexOf(final Iterator> iter, final Object objToFind) {
if (iter == null) {
return N.INDEX_NOT_FOUND;
}
long index = 0;
while (iter.hasNext()) {
if (N.equals(iter.next(), objToFind)) {
return index;
}
index++;
}
return N.INDEX_NOT_FOUND;
}
/**
*
* @param iter
* @param objToFind
* @return
*/
public static long occurrencesOf(final Iterator> iter, final Object objToFind) {
if (iter == null) {
return 0;
}
long occurrences = 0;
while (iter.hasNext()) {
if (N.equals(iter.next(), objToFind)) {
occurrences++;
}
}
return occurrences;
}
/**
*
* @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 iter
* @param filter
* @return
*/
public static long count(final Iterator iter, final Predicate super T> filter) {
N.checkArgNotNull(filter);
if (iter == null) {
return 0;
}
long res = 0;
while (iter.hasNext()) {
if (filter.test(iter.next())) {
res++;
}
}
return res;
}
/**
*
* @param
* @param iter
* @return
*/
public static List toList(final Iterator extends T> iter) {
if (iter == null) {
return new ArrayList<>();
}
final List result = new ArrayList<>();
while (iter.hasNext()) {
result.add(iter.next());
}
return result;
}
/**
*
* @param
* @param iter
* @return
*/
public static Set toSet(final Iterator extends T> iter) {
if (iter == null) {
return N.newHashSet();
}
final Set result = N.newHashSet();
while (iter.hasNext()) {
result.add(iter.next());
}
return result;
}
/**
*
* @param
* @param
* @param iter
* @param collectionFactory
* @return
*/
public static > C toCollection(final Iterator extends T> iter, final Supplier extends C> collectionFactory) {
final C c = collectionFactory.get();
if (iter == null) {
return c;
}
while (iter.hasNext()) {
c.add(iter.next());
}
return c;
}
/**
*
* @param
* @param the key type
* @param
* @param iter
* @param keyMapper
* @return
* @throws E the e
*/
public static Map toMap(final Iterator extends T> iter, final Throwables.Function super T, K, E> keyMapper) throws E {
N.checkArgNotNull(keyMapper);
if (iter == null) {
return new HashMap<>();
}
final Map result = new HashMap<>();
T e = null;
while (iter.hasNext()) {
e = iter.next();
result.put(keyMapper.apply(e), e);
}
return result;
}
/**
*
* @param
* @param the key type
* @param the value type
* @param
* @param
* @param iter
* @param keyMapper
* @param valueExtractor
* @return
* @throws E the e
* @throws E2 the e2
*/
public static Map toMap(final Iterator extends T> iter,
final Throwables.Function super T, K, E> keyMapper, final Throwables.Function super T, ? extends V, E2> valueExtractor) throws E, E2 {
N.checkArgNotNull(keyMapper);
N.checkArgNotNull(valueExtractor);
if (iter == null) {
return new HashMap<>();
}
final Map result = new HashMap<>();
T e = null;
while (iter.hasNext()) {
e = iter.next();
result.put(keyMapper.apply(e), valueExtractor.apply(e));
}
return result;
}
/**
*
* @param
* @param the key type
* @param the value type
* @param
* @param
* @param
* @param iter
* @param keyMapper
* @param valueExtractor
* @param mapSupplier
* @return
* @throws E the e
* @throws E2 the e2
*/
public static , E extends Exception, E2 extends Exception> M toMap(final Iterator extends T> iter,
final Throwables.Function super T, K, E> keyMapper, final Throwables.Function super T, ? extends V, E2> valueExtractor,
final Supplier extends M> mapSupplier) throws E, E2 {
N.checkArgNotNull(keyMapper);
N.checkArgNotNull(valueExtractor);
if (iter == null) {
return mapSupplier.get();
}
final M result = mapSupplier.get();
T e = null;
while (iter.hasNext()) {
e = iter.next();
result.put(keyMapper.apply(e), valueExtractor.apply(e));
}
return result;
}
/**
*
* @param
* @param
* @param iter
* @param action
* @throws E the e
*/
public static void forEach(final Iterator iter, final Throwables.Consumer super T, E> action) throws E {
N.checkArgNotNull(action);
if (iter == null) {
return;
}
while (iter.hasNext()) {
action.accept(iter.next());
}
}
/**
*
* @param
* @param
* @param iter
* @param action
* @throws E the e
*/
public static void forEachIndexed(final Iterator iter, final Throwables.IndexedConsumer super T, E> action) throws E {
N.checkArgNotNull(action);
if (iter == null) {
return;
}
int idx = 0;
while (iter.hasNext()) {
action.accept(idx++, iter.next());
}
}
/**
*
* @param
* @param
* @param
* @param
* @param iter
* @param flatMapper
* @param action
* @throws E the e
* @throws E2 the e2
*/
public static void forEach(final Iterator iter,
final Throwables.Function super T, ? extends Collection, E> flatMapper, final Throwables.BiConsumer super T, ? super U, E2> action)
throws E, E2 {
N.checkArgNotNull(flatMapper);
N.checkArgNotNull(action);
if (iter == null) {
return;
}
T e = null;
while (iter.hasNext()) {
e = iter.next();
final Collection c2 = flatMapper.apply(e);
if (N.notNullOrEmpty(c2)) {
for (U u : c2) {
action.accept(e, u);
}
}
}
}
/**
*
* @param
* @param
* @param
* @param
* @param
* @param
* @param iter
* @param flatMapper
* @param flatMapper2
* @param action
* @throws E the e
* @throws E2 the e2
* @throws E3 the e3
*/
public static void forEach(final Iterator iter,
final Throwables.Function super T, ? extends Collection, E> flatMapper,
final Throwables.Function super T2, ? extends Collection, E2> flatMapper2,
final Throwables.TriConsumer super T, ? super T2, ? super T3, E3> action) throws E, E2, E3 {
N.checkArgNotNull(flatMapper);
N.checkArgNotNull(flatMapper2);
N.checkArgNotNull(action);
if (iter == null) {
return;
}
T e = null;
while (iter.hasNext()) {
e = iter.next();
final Collection c2 = flatMapper.apply(e);
if (N.notNullOrEmpty(c2)) {
for (T2 t2 : c2) {
final Collection c3 = flatMapper2.apply(t2);
if (N.notNullOrEmpty(c3)) {
for (T3 t3 : c3) {
action.accept(e, t2, t3);
}
}
}
}
}
}
/**
*
* @param
* @param
* @param
* @param a
* @param b
* @param action
* @throws E the e
*/
public static void forEach(final Iterator a, final Iterator b,
final Throwables.BiConsumer super A, ? super B, E> action) throws E {
N.checkArgNotNull(action);
if (a == null || b == null) {
return;
}
while (a.hasNext() && b.hasNext()) {
action.accept(a.next(), b.next());
}
}
/**
*
* @param
* @param
* @param
* @param
* @param a
* @param b
* @param c
* @param action
* @throws E the e
*/
public static void forEach(final Iterator a, final Iterator b, final Iterator c,
final Throwables.TriConsumer super A, ? super B, ? super C, E> action) throws E {
N.checkArgNotNull(action);
if (a == null || b == null || c == null) {
return;
}
while (a.hasNext() && b.hasNext() && c.hasNext()) {
action.accept(a.next(), b.next(), c.next());
}
}
/**
*
* @param
* @param
* @param
* @param a
* @param b
* @param valueForNoneA
* @param valueForNoneB
* @param action
* @throws E the e
*/
public static void forEach(final Iterator a, final Iterator b, final A valueForNoneA, final B valueForNoneB,
final Throwables.BiConsumer super A, ? super B, E> action) throws E {
N.checkArgNotNull(action);
final Iterator iterA = a == null ? ObjIterator. empty() : a;
final Iterator iterB = b == null ? ObjIterator. empty() : b;
A nextA = null;
B nextB = null;
while (iterA.hasNext() || iterB.hasNext()) {
nextA = iterA.hasNext() ? iterA.next() : valueForNoneA;
nextB = iterB.hasNext() ? iterB.next() : valueForNoneB;
action.accept(nextA, nextB);
}
}
/**
*
* @param
* @param
* @param
* @param
* @param a
* @param b
* @param c
* @param valueForNoneA
* @param valueForNoneB
* @param valueForNoneC
* @param action
* @throws E the e
*/
public static void forEach(final Iterator a, final Iterator b, final Iterator c, final A valueForNoneA,
final B valueForNoneB, final C valueForNoneC, final Throwables.TriConsumer super A, ? super B, ? super C, E> action) throws E {
N.checkArgNotNull(action);
final Iterator iterA = a == null ? ObjIterator. empty() : a;
final Iterator iterB = b == null ? ObjIterator. empty() : b;
final Iterator iterC = b == null ? ObjIterator. empty() : c;
A nextA = null;
B nextB = null;
C nextC = null;
while (iterA.hasNext() || iterB.hasNext() || iterC.hasNext()) {
nextA = iterA.hasNext() ? iterA.next() : valueForNoneA;
nextB = iterB.hasNext() ? iterB.next() : valueForNoneB;
nextC = iterC.hasNext() ? iterC.next() : valueForNoneC;
action.accept(nextA, nextB, nextC);
}
}
/**
* For each non null.
*
* @param
* @param
* @param
* @param
* @param iter
* @param flatMapper
* @param action
* @throws E the e
* @throws E2 the e2
*/
public static void forEachNonNull(final Iterator iter,
final Throwables.Function super T, ? extends Collection, E> flatMapper, final Throwables.BiConsumer super T, ? super U, E2> action)
throws E, E2 {
N.checkArgNotNull(flatMapper);
N.checkArgNotNull(action);
if (iter == null) {
return;
}
T e = null;
while (iter.hasNext()) {
e = iter.next();
if (e != null) {
final Collection c2 = flatMapper.apply(e);
if (N.notNullOrEmpty(c2)) {
for (U u : c2) {
if (u != null) {
action.accept(e, u);
}
}
}
}
}
}
/**
* For each non null.
*
* @param
* @param
* @param
* @param
* @param
* @param
* @param iter
* @param flatMapper
* @param flatMapper2
* @param action
* @throws E the e
* @throws E2 the e2
* @throws E3 the e3
*/
public static void forEachNonNull(final Iterator iter,
final Throwables.Function super T, ? extends Collection, E> flatMapper,
final Throwables.Function super T2, ? extends Collection, E2> flatMapper2,
final Throwables.TriConsumer super T, ? super T2, ? super T3, E3> action) throws E, E2, E3 {
N.checkArgNotNull(flatMapper);
N.checkArgNotNull(flatMapper2);
N.checkArgNotNull(action);
if (iter == null) {
return;
}
T e = null;
while (iter.hasNext()) {
e = iter.next();
if (e != null) {
final Collection c2 = flatMapper.apply(e);
if (N.notNullOrEmpty(c2)) {
for (T2 t2 : c2) {
if (t2 != null) {
final Collection c3 = flatMapper2.apply(t2);
if (N.notNullOrEmpty(c3)) {
for (T3 t3 : c3) {
if (t3 != null) {
action.accept(e, t2, t3);
}
}
}
}
}
}
}
}
}
/**
* For each pair.
*
* @param
* @param
* @param iter
* @param action
* @throws E the e
*/
public static void forEachPair(final Iterator iter, final Throwables.BiConsumer super T, ? super T, E> action) throws E {
forEachPair(iter, action, 1);
}
/**
* For each pair.
*
* @param
* @param
* @param iter
* @param action
* @param increment
* @throws E the e
*/
public static void forEachPair(final Iterator iter, final Throwables.BiConsumer super T, ? super T, E> action,
final int increment) throws E {
N.checkArgNotNull(action);
final int windowSize = 2;
N.checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment);
if (iter == null) {
return;
}
boolean isFirst = true;
T prev = null;
while (iter.hasNext()) {
if (increment > windowSize && isFirst == false) {
int skipNum = increment - windowSize;
while (skipNum-- > 0 && iter.hasNext()) {
iter.next();
}
if (iter.hasNext() == false) {
break;
}
}
if (increment == 1) {
action.accept(isFirst ? iter.next() : prev, (prev = (iter.hasNext() ? iter.next() : null)));
} else {
action.accept(iter.next(), iter.hasNext() ? iter.next() : null);
}
isFirst = false;
}
}
/**
* For each triple.
*
* @param
* @param
* @param iter
* @param action
* @throws E the e
*/
public static void forEachTriple(final Iterator iter, final Throwables.TriConsumer super T, ? super T, ? super T, E> action)
throws E {
forEachTriple(iter, action, 1);
}
/**
* For each triple.
*
* @param
* @param
* @param iter
* @param action
* @param increment
* @throws E the e
*/
public static void forEachTriple(final Iterator iter, final Throwables.TriConsumer super T, ? super T, ? super T, E> action,
final int increment) throws E {
N.checkArgNotNull(action);
final int windowSize = 3;
N.checkArgument(windowSize > 0 && increment > 0, "windowSize=%s and increment=%s must be bigger than 0", windowSize, increment);
if (iter == null) {
return;
}
boolean isFirst = true;
T prev = null;
T prev2 = null;
while (iter.hasNext()) {
if (increment > windowSize && isFirst == false) {
int skipNum = increment - windowSize;
while (skipNum-- > 0 && iter.hasNext()) {
iter.next();
}
if (iter.hasNext() == false) {
break;
}
}
if (increment == 1) {
action.accept(isFirst ? iter.next() : prev2, (prev2 = (isFirst ? (iter.hasNext() ? iter.next() : null) : prev)),
(prev = (iter.hasNext() ? iter.next() : null)));
} else if (increment == 2) {
action.accept(isFirst ? iter.next() : prev, iter.hasNext() ? iter.next() : null, (prev = (iter.hasNext() ? iter.next() : null)));
} else {
action.accept(iter.next(), iter.hasNext() ? iter.next() : null, iter.hasNext() ? iter.next() : null);
}
isFirst = false;
}
}
/**
*
* @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);
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() == false) {
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() == false) {
throw new NoSuchElementException();
}
if (iter == null || iter.hasNext() == false) {
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() == false) {
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() == false) {
throw new NoSuchElementException();
}
if (iter == null || iter.hasNext() == false) {
iter = c.iterator();
}
cnt--;
return iter.next();
}
};
}
/**
*
* @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 Collection extends T>... a) {
if (N.isNullOrEmpty(a)) {
return ObjIterator.empty();
}
final List> list = new ArrayList<>(a.length);
for (Collection extends T> e : a) {
if (N.notNullOrEmpty(e)) {
list.add(e.iterator());
}
}
return concat(list);
}
/**
*
* @param
* @param c
* @return
*/
public static ObjIterator concatt(final Collection extends Collection extends T>> c) {
if (N.isNullOrEmpty(c)) {
return ObjIterator.empty();
}
return new ObjIterator() {
private final Iterator extends Collection extends T>> iter = c.iterator();
private Iterator extends T> cur;
@Override
public boolean hasNext() {
while ((cur == null || cur.hasNext() == false) && iter.hasNext()) {
final Collection extends T> c = iter.next();
cur = N.isNullOrEmpty(c) ? null : c.iterator();
}
return cur != null && cur.hasNext();
}
@Override
public T next() {
if ((cur == null || cur.hasNext() == false) && hasNext() == false) {
throw new NoSuchElementException();
}
return cur.next();
}
};
}
/**
*
* @param
* @param a
* @return
*/
@SafeVarargs
public static ObjIterator concat(final Iterator extends T>... a) {
if (N.isNullOrEmpty(a)) {
return ObjIterator.empty();
}
return concat(Array.asList(a));
}
/**
*
* @param
* @param c
* @return
*/
public static ObjIterator concat(final Collection extends Iterator extends T>> c) {
if (N.isNullOrEmpty(c)) {
return ObjIterator.empty();
}
return new ObjIterator() {
private final Iterator extends Iterator extends T>> iter = c.iterator();
private Iterator extends T> cur;
@Override
public boolean hasNext() {
while ((cur == null || cur.hasNext() == false) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public T next() {
if ((cur == null || cur.hasNext() == false) && hasNext() == false) {
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() == false) && iter.hasNext()) {
cur = iter.next();
}
return cur != null && cur.hasNext();
}
@Override
public Pair next() {
if ((cur == null || cur.hasNext() == false) && hasNext() == false) {
throw new NoSuchElementException();
}
return cur.next();
}
@Override
public void forEachRemaining(final Throwables.BiConsumer super A, ? super B, E> action) throws E {
while (hasNext()) {
cur.forEachRemaining(action);
}
}
@Override
public ObjIterator map(final BiFunction super A, ? super B, R> mapper) {
N.checkArgNotNull(mapper);
return new ObjIterator() {
private ObjIterator mappedIter = null;
@Override
public boolean hasNext() {
if (mappedIter == null || mappedIter.hasNext() == false) {
while ((cur == null || cur.hasNext() == false) && iter.hasNext()) {
cur = iter.next();
}
if (cur != null) {
mappedIter = cur.map(mapper);
}
}
return mappedIter != null && mappedIter.hasNext();
}
@Override
public R next() {
if (hasNext() == false) {
throw new NoSuchElementException();
}
return mappedIter.next();
}
};
}
};
}
/**
*
* @param
* @param a
* @param b
* @param nextSelector
* @return
*/
public static ObjIterator merge(final Collection extends T> a, final Collection extends T> b,
final BiFunction super T, ? super T, MergeResult> nextSelector) {
final Iterator iterA = N.isNullOrEmpty(a) ? ObjIterator. empty() : (Iterator) a.iterator();
final Iterator iterB = N.isNullOrEmpty(b) ? ObjIterator. empty() : (Iterator) b.iterator();
return merge(iterA, iterB, nextSelector);
}
/**
*
* @param
* @param a
* @param b
* @param nextSelector
* @return
*/
public static ObjIterator merge(final Iterator extends T> a, final Iterator extends T> b,
final BiFunction super T, ? super T, MergeResult> nextSelector) {
N.checkArgNotNull(nextSelector);
return new ObjIterator() {
private final Iterator extends T> iterA = a == null ? ObjIterator. empty() : a;
private final Iterator extends T> 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
* @param
* @param a
* @param b
* @param zipFunction
* @return
*/
public static ObjIterator zip(final Collection a, final Collection b, final BiFunction super A, ? super B, R> zipFunction) {
final Iterator iterA = N.isNullOrEmpty(a) ? ObjIterator. empty() : a.iterator();
final Iterator iterB = N.isNullOrEmpty(b) ? ObjIterator. empty() : b.iterator();
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 super A, ? super B, R> 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 Collection a, final Collection b, final Collection c,
final TriFunction super A, ? super B, ? super C, R> zipFunction) {
final Iterator iterA = N.isNullOrEmpty(a) ? ObjIterator. empty() : a.iterator();
final Iterator iterB = N.isNullOrEmpty(b) ? ObjIterator. empty() : b.iterator();
final Iterator iterC = N.isNullOrEmpty(c) ? ObjIterator. empty() : c.iterator();
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 super A, ? super B, ? super C, R> zipFunction) {
N.checkArgNotNull(zipFunction);
return new ObjIterator() {
private final Iterator iterA = a == null ? ObjIterator. empty() : a;
private final Iterator iterB = b == null ? ObjIterator.