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

com.landawn.abacus.util.Iterators Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

There is a newer version: 5.2.4
Show newest version
/*
 * 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 ObjIterator distinctBy(final Iterator iter, final Function keyMapper) { 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(keyMapper.apply(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 predicate * @return */ public static ObjIterator filter(final Iterator iter, final Predicate predicate) { N.checkArgNotNull(predicate, "predicate"); if (iter == null) { return ObjIterator.empty(); } 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 (predicate.test(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 predicate * @return */ public static ObjIterator takeWhile(final Iterator iter, final Predicate predicate) { N.checkArgNotNull(predicate, "predicate"); if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private final T NONE = (T) N.NULL_MASK; //NOSONAR private T next = NONE; private T tmp = null; private boolean hasMore = true; @Override public boolean hasNext() { if (next == NONE && hasMore && iter.hasNext()) { tmp = iter.next(); if (predicate.test(tmp)) { next = tmp; } else { hasMore = false; } } return next != NONE; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } tmp = next; next = NONE; return tmp; } }; } /** * * * @param * @param iter * @param predicate * @return */ public static ObjIterator takeWhileInclusive(final Iterator iter, final Predicate predicate) { N.checkArgNotNull(predicate, "predicate"); if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private final T NONE = (T) N.NULL_MASK; //NOSONAR private T next = NONE; private T tmp = null; private boolean hasMore = true; @Override public boolean hasNext() { if (next == NONE && hasMore && iter.hasNext()) { tmp = iter.next(); if (predicate.test(tmp)) { next = tmp; } else { next = tmp; hasMore = false; } } return next != NONE; } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } tmp = next; next = NONE; return tmp; } }; } /** * * * @param * @param iter * @param predicate * @return */ public static ObjIterator dropWhile(final Iterator iter, final Predicate predicate) { N.checkArgNotNull(predicate, "predicate"); if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private final T NONE = (T) N.NULL_MASK; //NOSONAR private T next = NONE; private boolean hasDropped = false; @Override public boolean hasNext() { if (!hasDropped) { while (iter.hasNext()) { next = iter.next(); if (predicate.test(next)) { next = NONE; } else { hasDropped = true; break; } } } return next != NONE || iter.hasNext(); } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } if (next != NONE) { final T tmp = next; next = NONE; return tmp; } else { return iter.next(); } } }; } /** * * * @param * @param iter * @param predicate * @return */ public static ObjIterator skipUntil(final Iterator iter, final Predicate predicate) { N.checkArgNotNull(predicate, "predicate"); if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private final T NONE = (T) N.NULL_MASK; //NOSONAR private T next = NONE; private boolean hasSkipped = false; @Override public boolean hasNext() { if (!hasSkipped) { while (iter.hasNext()) { next = iter.next(); if (predicate.test(next)) { hasSkipped = true; break; } else { next = NONE; } } } return next != NONE || iter.hasNext(); } @Override public T next() { if (!hasNext()) { throw new NoSuchElementException(); } if (next != NONE) { final T tmp = next; next = NONE; return tmp; } else { return iter.next(); } } }; } /** * * @param * @param * @param iter * @param mapper * @return */ public static ObjIterator map(final Iterator iter, final Function mapper) { N.checkArgNotNull(mapper, "mapper"); //NOSONAR if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { @Override public boolean hasNext() { return iter.hasNext(); } @Override public U next() { return mapper.apply(iter.next()); } }; } /** * * @param * @param * @param iter * @param mapper * @return */ public static ObjIterator flatMap(final Iterator iter, final Function> mapper) { N.checkArgNotNull(mapper, "mapper"); if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private Collection c = null; private Iterator cur = null; @Override public boolean hasNext() { if (cur == null || !cur.hasNext()) { while (iter.hasNext()) { c = mapper.apply(iter.next()); cur = c == null || c.size() == 0 ? null : c.iterator(); if (cur != null && cur.hasNext()) { break; } } } return cur != null && cur.hasNext(); } @Override public U next() { if (!hasNext()) { throw new NoSuchElementException(); } return cur.next(); } }; } /** * * * @param * @param * @param iter * @param mapper * @return */ public static ObjIterator flatmap(final Iterator iter, final Function mapper) { //NOSONAR N.checkArgNotNull(mapper, "mapper"); if (iter == null) { return ObjIterator.empty(); } return new ObjIterator<>() { private U[] a = null; private int len = 0; private int cursor = 0; @Override public boolean hasNext() { if (cursor >= len) { while (iter.hasNext()) { a = mapper.apply(iter.next()); len = N.len(a); cursor = 0; if (len > 0) { break; } } } return cursor < len; } @Override public U next() { if (!hasNext()) { throw new NoSuchElementException(); } return a[cursor++]; } }; } /** * * @param * @param * @param iter * @param elementParser * @throws E the e */ public static void forEach(final Iterator iter, final Throwables.Consumer elementParser) throws E { forEach(iter, elementParser, Fn.emptyAction()); } /** * * @param * @param * @param * @param iter * @param elementParser * @param onComplete * @throws E the e * @throws E2 the e2 */ public static void forEach(final Iterator iter, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { forEach(iter, 0, Long.MAX_VALUE, elementParser, onComplete); } /** * * @param * @param * @param iter * @param offset * @param count * @param elementParser * @throws E the e */ public static void forEach(final Iterator iter, final long offset, final long count, final Throwables.Consumer elementParser) throws E { forEach(iter, offset, count, elementParser, Fn.emptyAction()); } /** * * @param * @param * @param * @param iter * @param offset * @param count * @param elementParser * @param onComplete * @throws E the e * @throws E2 the e2 */ public static void forEach(final Iterator iter, final long offset, final long count, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { forEach(iter, offset, count, 0, 0, elementParser, onComplete); } /** * * @param * @param * @param iter * @param offset * @param count * @param processThreadNum * @param queueSize * @param elementParser * @throws E the e */ public static void forEach(final Iterator iter, long offset, long count, final int processThreadNum, final int queueSize, final Throwables.Consumer elementParser) throws E { forEach(iter, offset, count, processThreadNum, queueSize, elementParser, Fn.emptyAction()); } /** * Parse the elements in the specified iterators one by one. * * @param * @param * @param * @param iter * @param offset * @param count * @param processThreadNum new threads started to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param elementParser * @param onComplete * @throws E the e * @throws E2 the e2 */ public static void forEach(final Iterator iter, long offset, long count, final int processThreadNum, final int queueSize, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { forEach(Array.asList(iter), offset, count, 0, processThreadNum, queueSize, elementParser, onComplete); } /** * * @param * @param * @param iterators * @param elementParser * @throws E the e */ public static void forEach(final Collection> iterators, final Throwables.Consumer elementParser) throws E { forEach(iterators, elementParser, Fn.emptyAction()); } /** * * @param * @param * @param * @param iterators * @param elementParser * @param onComplete * @throws E the e * @throws E2 the e2 */ public static void forEach(final Collection> iterators, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { forEach(iterators, 0, Long.MAX_VALUE, elementParser, onComplete); } /** * * @param * @param * @param iterators * @param offset * @param count * @param elementParser * @throws E the e */ public static void forEach(final Collection> iterators, final long offset, final long count, final Throwables.Consumer elementParser) throws E { forEach(iterators, offset, count, elementParser, Fn.emptyAction()); } /** * * @param * @param * @param * @param iterators * @param offset * @param count * @param elementParser * @param onComplete * @throws E the e * @throws E2 the e2 */ public static void forEach(final Collection> iterators, final long offset, final long count, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { forEach(iterators, offset, count, 0, 0, 0, elementParser, onComplete); } /** * * @param * @param * @param iterators * @param readThreadNum * @param processThreadNum * @param queueSize * @param elementParser * @throws E the e */ public static void forEach(final Collection> iterators, final int readThreadNum, final int processThreadNum, final int queueSize, final Throwables.Consumer elementParser) throws E { forEach(iterators, readThreadNum, processThreadNum, queueSize, elementParser, Fn.emptyAction()); } /** * * * @param * @param * @param * @param iterators * @param readThreadNum * @param processThreadNum * @param queueSize * @param elementParser * @param onComplete * @throws E the e * @throws E2 */ public static void forEach(final Collection> iterators, final int readThreadNum, final int processThreadNum, final int queueSize, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { forEach(iterators, 0, Long.MAX_VALUE, readThreadNum, processThreadNum, queueSize, elementParser, onComplete); } /** * * @param * @param * @param iterators * @param offset * @param count * @param readThreadNum * @param processThreadNum * @param queueSize * @param elementParser * @throws E the e */ public static void forEach(final Collection> iterators, final long offset, final long count, final int readThreadNum, final int processThreadNum, final int queueSize, final Throwables.Consumer elementParser) throws E { forEach(iterators, offset, count, readThreadNum, processThreadNum, queueSize, elementParser, Fn.emptyAction()); } /** * Parse the elements in the specified iterators one by one. * * @param * @param * @param * @param iterators * @param offset * @param count * @param readThreadNum new threads started to parse/process the lines/records * @param processThreadNum new threads started to parse/process the lines/records * @param queueSize size of queue to save the processing records/lines loaded from source data. Default size is 1024. * @param elementParser * @param onComplete * @throws E the e * @throws E2 the e2 */ public static void forEach(final Collection> iterators, final long offset, final long count, final int readThreadNum, final int processThreadNum, final int queueSize, final Throwables.Consumer elementParser, final Throwables.Runnable onComplete) throws E, E2 { N.checkArgument(offset >= 0 && count >= 0, "'offset'=%s and 'count'=%s can not be negative", offset, count); if (N.isNullOrEmpty(iterators)) { return; } if (logger.isInfoEnabled()) { logger.info("### Start to process"); } try (final Stream stream = ((readThreadNum > 0 || queueSize > 0) ? Stream.parallelConcatIterators(iterators, (readThreadNum == 0 ? 1 : readThreadNum), (queueSize == 0 ? 1024 : queueSize)) : Stream.concatIterators(iterators))) { final Iterator iteratorII = stream.skip(offset).limit(count).iterator(); if (processThreadNum == 0) { while (iteratorII.hasNext()) { elementParser.accept(iteratorII.next()); } if (onComplete != null) { onComplete.run(); } } else { final AtomicInteger activeThreadNum = new AtomicInteger(); final ExecutorService executorService = Executors.newFixedThreadPool(processThreadNum); final Holder errorHolder = new Holder<>(); for (int i = 0; i < processThreadNum; i++) { activeThreadNum.incrementAndGet(); executorService.execute(() -> { T element = null; try { while (errorHolder.value() == null) { synchronized (iteratorII) { if (iteratorII.hasNext()) { element = iteratorII.next(); } else { break; } } elementParser.accept(element); } } catch (Exception e) { synchronized (errorHolder) { if (errorHolder.value() == null) { errorHolder.setValue(e); } else { errorHolder.value().addSuppressed(e); } } } finally { activeThreadNum.decrementAndGet(); } }); } while (activeThreadNum.get() > 0) { N.sleep(1); } if (errorHolder.value() == null && onComplete != null) { try { onComplete.run(); } catch (Exception e) { errorHolder.setValue(e); } } if (errorHolder.value() != null) { throw ExceptionUtil.toRuntimeException(errorHolder.value()); } } } finally { if (logger.isInfoEnabled()) { logger.info("### End to process"); } } } }