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

com.strobel.core.CollectionUtilities Maven / Gradle / Ivy

/*
 * CollectionUtilities.java
 *
 * Copyright (c) 2012 Mike Strobel
 *
 * This source code is subject to terms and conditions of the Apache License, Version 2.0.
 * A copy of the license can be found in the License.html file at the root of this distribution.
 * By using this source code in any fashion, you are agreeing to be bound by the terms of the
 * Apache License, Version 2.0.
 *
 * You must not remove this notice, or any other, from this software.
 */

package com.strobel.core;

import com.strobel.annotations.NotNull;
import com.strobel.annotations.Nullable;
import com.strobel.functions.Supplier;
import com.strobel.util.ContractUtils;
import com.strobel.util.EmptyArrayCache;

import java.lang.reflect.Array;
import java.util.*;

/**
 * @author Mike Strobel
 */
public final class CollectionUtilities {
    private final static Supplier IDENTITY_MAP_SUPPLIER = new Supplier() {
        @Override
        public Map get() {
            return new IdentityHashMap<>();
        }
    };

    private final static Supplier HASH_MAP_SUPPLIER = new Supplier() {
        @Override
        public Map get() {
            return new HashMap<>();
        }
    };

    private final static Supplier LINKED_HASH_MAP_SUPPLIER = new Supplier() {
        @Override
        public Map get() {
            return new LinkedHashMap<>();
        }
    };

    private final static Supplier LIST_SUPPLIER = new Supplier() {
        @Override
        public List get() {
            return new ArrayList<>();
        }
    };

    private final static Supplier SET_SUPPLIER = new Supplier() {
        @Override
        public Set get() {
            return new LinkedHashSet<>();
        }
    };

    @SuppressWarnings("unchecked")
    public static  Supplier> setFactory() {
        return (Supplier>) SET_SUPPLIER;
    }

    @SuppressWarnings("unchecked")
    public static  Supplier> listFactory() {
        return (Supplier>) LIST_SUPPLIER;
    }

    @SuppressWarnings("unchecked")
    public static  Supplier> hashMapFactory() {
        return (Supplier>) HASH_MAP_SUPPLIER;
    }

    @SuppressWarnings("unchecked")
    public static  Supplier> linekdHashMapFactory() {
        return (Supplier>) LINKED_HASH_MAP_SUPPLIER;
    }

    @SuppressWarnings("unchecked")
    public static  Supplier> identityMapFactory() {
        return (Supplier>) IDENTITY_MAP_SUPPLIER;
    }

    public static  int indexOfByIdentity(final List collection, final T item) {
        for (int i = 0, n = collection.size(); i < n; i++) {
            if (collection.get(i) == item) {
                return i;
            }
        }
        return -1;
    }

    public static  int indexOfByIdentity(final Iterable collection, final T item) {
        VerifyArgument.notNull(collection, "collection");

        if (collection instanceof List) {
            return indexOfByIdentity((List) collection, item);
        }

        int i = -1;

        for (final Object o : collection) {
            ++i;

            if (o == item) {
                return i;
            }
        }

        return -1;
    }

    public static  int indexOf(final Iterable collection, final T item) {
        VerifyArgument.notNull(collection, "collection");

        if (collection instanceof List) {
            return ((List) collection).indexOf(item);
        }

        int i = -1;

        for (final Object o : collection) {
            ++i;

            if (Objects.equals(o, item)) {
                return i;
            }
        }

        return -1;
    }

    public static  List toList(final Enumeration collection) {
        if (!collection.hasMoreElements()) {
            return Collections.emptyList();
        }

        final ArrayList list = new ArrayList<>();

        while (collection.hasMoreElements()) {
            list.add(collection.nextElement());
        }

        return list;
    }

    public static  List toList(final Iterable collection) {
        final ArrayList list = new ArrayList<>();

        for (final T item : collection) {
            list.add(item);
        }

        return list;
    }

    public static  T getOrDefault(final Iterable collection, final int index) {
        int i = 0;

        for (final T item : collection) {
            if (i++ == index) {
                return item;
            }
        }

        return null;
    }

    public static  T getOrDefault(final List collection, final int index) {
        if (index >= VerifyArgument.notNull(collection, "collection").size() || index < 0) {
            return null;
        }
        return collection.get(index);
    }

    public static  T get(final Iterable collection, final int index) {
        if (VerifyArgument.notNull(collection, "collection") instanceof List) {
            return get((List) collection, index);
        }

        int i = 0;

        for (final T item : collection) {
            if (i++ == index) {
                return item;
            }
        }

        throw Error.indexOutOfRange(index);
    }

    public static  T get(final List list, final int index) {
        if (index >= VerifyArgument.notNull(list, "list").size() || index < 0) {
            throw Error.indexOutOfRange(index);
        }
        return list.get(index);
    }

    public static  T single(final List list) {
        switch (VerifyArgument.notNull(list, "list").size()) {
            case 0:
                throw Error.sequenceHasNoElements();
            case 1:
                return list.get(0);
            default:
                throw Error.sequenceHasMultipleElements();
        }
    }

    public static  T singleOrDefault(final List list) {
        switch (VerifyArgument.notNull(list, "list").size()) {
            case 0:
                return null;
            case 1:
                return list.get(0);
            default:
                throw Error.sequenceHasMultipleElements();
        }
    }

    public static  T single(final Iterable collection) {
        if (collection instanceof List) {
            return single((List) collection);
        }

        final Iterator it = VerifyArgument.notNull(collection, "collection").iterator();

        if (it.hasNext()) {
            final T result = it.next();

            if (it.hasNext()) {
                throw Error.sequenceHasMultipleElements();
            }

            return result;
        }

        throw Error.sequenceHasNoElements();
    }

    public static  T first(final List list) {
        if (VerifyArgument.notNull(list, "list").isEmpty()) {
            throw Error.sequenceHasNoElements();
        }
        return list.get(0);
    }

    public static  T first(final Iterable collection) {
        if (collection instanceof List) {
            return first((List) collection);
        }

        final Iterator it = VerifyArgument.notNull(collection, "collection").iterator();

        if (it.hasNext()) {
            return it.next();
        }

        throw Error.sequenceHasNoElements();
    }

    public static  T singleOrDefault(final Iterable collection) {
        if (collection instanceof List) {
            return singleOrDefault((List) collection);
        }

        final Iterator it = VerifyArgument.notNull(collection, "collection").iterator();

        if (it.hasNext()) {
            final T result = it.next();

            if (it.hasNext()) {
                throw Error.sequenceHasMultipleElements();
            }

            return result;
        }

        return null;
    }

    public static  Iterable ofType(final Iterable collection, final Class type) {
        return new OfTypeIterator<>(VerifyArgument.notNull(collection, "collection"), type);
    }

    public static  T firstOrDefault(final Iterable collection) {
        final Iterator it = VerifyArgument.notNull(collection, "collection").iterator();
        return it.hasNext() ? it.next() : null;
    }

    public static  T first(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(predicate, "predicate");

        for (final T item : VerifyArgument.notNull(collection, "collection")) {
            if (predicate.test(item)) {
                return item;
            }
        }

        throw Error.sequenceHasNoElements();
    }

    public static  T firstOrDefault(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(predicate, "predicate");

        for (final T item : VerifyArgument.notNull(collection, "collection")) {
            if (predicate.test(item)) {
                return item;
            }
        }

        return null;
    }

    public static  T last(final List list) {
        if (VerifyArgument.notNull(list, "list").isEmpty()) {
            throw Error.sequenceHasNoElements();
        }

        return list.get(list.size() - 1);
    }

    public static  T last(final Iterable collection) {
        VerifyArgument.notNull(collection, "collection");

        if (collection instanceof List) {
            return last((List) collection);
        }

        final Iterator iterator = collection.iterator();
        final boolean hasAny = iterator.hasNext();

        if (!hasAny) {
            throw Error.sequenceHasNoElements();
        }

        T last;

        do {
            last = iterator.next();
        }
        while (iterator.hasNext());

        return last;
    }

    public static  T lastOrDefault(final Iterable collection) {
        VerifyArgument.notNull(collection, "collection");

        if (collection instanceof List) {
            final List list = (List) collection;
            return list.isEmpty() ? null : list.get(list.size() - 1);
        }

        T last = null;

        for (final T item : collection) {
            last = item;
        }

        return last;
    }

    public static  int firstIndexWhere(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(collection, "collection");
        VerifyArgument.notNull(predicate, "predicate");

        int index = 0;

        for (final T item : VerifyArgument.notNull(collection, "collection")) {
            if (predicate.test(item)) {
                return index;
            }
            ++index;
        }

        return -1;
    }

    public static  int lastIndexWhere(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(collection, "collection");
        VerifyArgument.notNull(predicate, "predicate");

        int index = 0;
        int lastMatch = -1;

        for (final T item : VerifyArgument.notNull(collection, "collection")) {
            if (predicate.test(item)) {
                lastMatch = index;
            }
            ++index;
        }

        return lastMatch;
    }

    public static  T last(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(collection, "collection");
        VerifyArgument.notNull(predicate, "predicate");

        T lastMatch = null;
        boolean matchFound = false;

        for (final T item : VerifyArgument.notNull(collection, "collection")) {
            if (predicate.test(item)) {
                lastMatch = item;
                matchFound = true;
            }
        }

        if (matchFound) {
            return lastMatch;
        }

        throw Error.sequenceHasNoElements();
    }

    public static  T lastOrDefault(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(collection, "collection");
        VerifyArgument.notNull(predicate, "predicate");

        T lastMatch = null;

        for (final T item : VerifyArgument.notNull(collection, "collection")) {
            if (predicate.test(item)) {
                lastMatch = item;
            }
        }

        return lastMatch;
    }

    public static  boolean contains(final Iterable collection, final T node) {
        if (collection instanceof Collection) {
            return ((Collection) collection).contains(node);
        }

        for (final Object item : collection) {
            if (Comparer.equals(item, node)) {
                return true;
            }
        }
        return false;
    }

    public static  boolean any(final Iterable collection) {
        if (collection instanceof Collection) {
            return !((Collection) collection).isEmpty();
        }
        return collection != null && collection.iterator().hasNext();
    }

    public static  Iterable skip(final Iterable collection, final int count) {
        return new SkipIterator<>(collection, count);
    }

    public static  Iterable skipWhile(final Iterable collection, final Predicate filter) {
        return new SkipIterator<>(collection, filter);
    }

    public static  Iterable take(final Iterable collection, final int count) {
        return new TakeIterator<>(collection, count);
    }

    public static  Iterable takeWhile(final Iterable collection, final Predicate filter) {
        return new TakeIterator<>(collection, filter);
    }

    public static  boolean any(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(collection, "collection");
        VerifyArgument.notNull(predicate, "predicate");

        for (final T t : collection) {
            if (predicate.test(t)) {
                return true;
            }
        }

        return false;
    }

    public static  boolean all(final Iterable collection, final Predicate predicate) {
        VerifyArgument.notNull(collection, "collection");
        VerifyArgument.notNull(predicate, "predicate");

        for (final T t : collection) {
            if (!predicate.test(t)) {
                return false;
            }
        }

        return true;
    }

    public static  Iterable where(final Iterable source, final Predicate filter) {
        VerifyArgument.notNull(source, "source");
        VerifyArgument.notNull(filter, "filter");

        if (source instanceof WhereSelectIterableIterator) {
            return ((WhereSelectIterableIterator) source).where(filter);
        }

        return new WhereSelectIterableIterator<>(source, filter, null);
    }

    public static  Iterable select(final Iterable source, final Selector selector) {
        VerifyArgument.notNull(source, "source");
        VerifyArgument.notNull(selector, "selector");

        if (source instanceof WhereSelectIterableIterator) {
            return ((WhereSelectIterableIterator) source).select(selector);
        }

        return new WhereSelectIterableIterator<>(source, null, selector);
    }

    public static int hashCode(final List sequence) {
        VerifyArgument.notNull(sequence, "sequence");

        int hashCode = HashUtilities.NullHashCode;

        for (int i = 0; i < sequence.size(); i++) {
            final Object item = sequence.get(i);

            final int itemHashCode;

            if (item instanceof Iterable) {
                itemHashCode = hashCode((Iterable) item);
            }
            else {
                itemHashCode = item != null ? HashUtilities.hashCode(item)
                                            : HashUtilities.NullHashCode;
            }

            hashCode = HashUtilities.combineHashCodes(
                hashCode,
                itemHashCode
            );
        }

        return hashCode;
    }

    public static int hashCode(final Iterable sequence) {
        if (sequence instanceof List) {
            return hashCode((List) sequence);
        }

        VerifyArgument.notNull(sequence, "sequence");

        int hashCode = HashUtilities.NullHashCode;

        for (final Object item : sequence) {
            final int itemHashCode;

            if (item instanceof Iterable) {
                itemHashCode = hashCode((Iterable) item);
            }
            else {
                itemHashCode = item != null ? HashUtilities.hashCode(item)
                                            : HashUtilities.NullHashCode;
            }

            hashCode = HashUtilities.combineHashCodes(
                hashCode,
                itemHashCode
            );
        }

        return hashCode;
    }

    public static  boolean sequenceEquals(final List first, final List second) {
        VerifyArgument.notNull(first, "first");
        VerifyArgument.notNull(second, "second");

        if (first == second) {
            return true;
        }

        if (first.size() != second.size()) {
            return false;
        }

        if (first.isEmpty()) {
            return true;
        }

        for (int i = 0, n = first.size(); i < n; i++) {
            if (!Comparer.equals(first.get(i), second.get(i))) {
                return false;
            }
        }

        return true;
    }

    public static  boolean sequenceEquals(final Iterable first, final Iterable second) {
        VerifyArgument.notNull(first, "first");
        VerifyArgument.notNull(second, "second");

        if (first == second) {
            return true;
        }

        if (first instanceof List && second instanceof List) {
            return sequenceDeepEquals((List) first, (List) second);
        }

        final Iterator firstIterator = first.iterator();
        final Iterator secondIterator = second.iterator();

        while (firstIterator.hasNext()) {
            if (!secondIterator.hasNext()) {
                return false;
            }

            if (!Comparer.equals(firstIterator.next(), secondIterator.next())) {
                return false;
            }
        }

        return !secondIterator.hasNext();
    }

    public static  boolean sequenceDeepEquals(final List first, final List second) {
        VerifyArgument.notNull(first, "first");
        VerifyArgument.notNull(second, "second");

        if (first == second) {
            return true;
        }

        if (first.size() != second.size()) {
            return false;
        }

        if (first.isEmpty()) {
            return true;
        }

        for (int i = 0, n = first.size(); i < n; i++) {
            if (!sequenceDeepEqualsCore(first.get(i), second.get(i))) {
                return false;
            }
        }

        return true;
    }

    public static  boolean sequenceDeepEquals(final Iterable first, final Iterable second) {
        VerifyArgument.notNull(first, "first");
        VerifyArgument.notNull(second, "second");

        if (first == second) {
            return true;
        }

        if (first instanceof List && second instanceof List) {
            return sequenceDeepEquals((List) first, (List) second);
        }

        final Iterator firstIterator = first.iterator();
        final Iterator secondIterator = second.iterator();

        while (firstIterator.hasNext()) {
            if (!secondIterator.hasNext()) {
                return false;
            }

            if (!sequenceDeepEqualsCore(firstIterator.next(), secondIterator.next())) {
                return false;
            }
        }

        return !secondIterator.hasNext();
    }

    private static boolean sequenceDeepEqualsCore(final Object first, final Object second) {
        if (first instanceof List) {
            return second instanceof List &&
                   sequenceDeepEquals((List) first, (List) second);
        }
        return Comparer.deepEquals(first, second);
    }

    public static  E[] toArray(final Class elementType, final Iterable sequence) {
        VerifyArgument.notNull(elementType, "elementType");
        VerifyArgument.notNull(sequence, "sequence");

        return new Buffer<>(elementType, sequence.iterator()).toArray();
    }

    public static  void removeAll(final @NotNull Map map, final @Nullable List keys) {
        if (keys == null || keys.isEmpty()) {
            return;
        }

        for (final K key : keys) {
            map.remove(key);
        }
    }

    private final static class Buffer {
        final Class elementType;

        E[] items;
        int count;

        @SuppressWarnings("unchecked")
        Buffer(final Class elementType, final Iterator source) {
            this.elementType = elementType;

            E[] items = null;
            int count = 0;

            if (source instanceof Collection) {
                final Collection collection = (Collection) source;

                count = collection.size();

                if (count > 0) {
                    items = (E[]) Array.newInstance(elementType, count);
                    collection.toArray(items);
                }
            }
            else {
                while (source.hasNext()) {
                    final E item = source.next();

                    if (items == null) {
                        items = (E[]) Array.newInstance(elementType, 4);
                    }
                    else if (items.length == count) {
                        items = Arrays.copyOf(items, count * 2);
                    }

                    items[count] = item;
                    count++;
                }
            }

            this.items = items;
            this.count = count;
        }

        E[] toArray() {
            if (count == 0) {
                return EmptyArrayCache.fromElementType(elementType);
            }

            if (items.length == count) {
                return items;
            }

            return Arrays.copyOf(items, count);
        }
    }

    private abstract static class AbstractIterator implements Iterable, Iterator {
        final static int STATE_UNINITIALIZED = 0;
        final static int STATE_NEED_NEXT = 1;
        final static int STATE_HAS_NEXT = 2;
        final static int STATE_FINISHED = 3;

        long threadId;
        int state;
        T next;

        AbstractIterator() {
            super();
            threadId = Thread.currentThread().getId();
        }

        @SuppressWarnings("CloneDoesntDeclareCloneNotSupportedException")
        protected abstract AbstractIterator clone();

        @Override
        public abstract boolean hasNext();

        @Override
        public T next() {
            if (!hasNext()) {
                throw new IllegalStateException();
            }
            state = STATE_NEED_NEXT;
            return next;
        }

        @NotNull
        @Override
        public Iterator iterator() {
            if (threadId == Thread.currentThread().getId() && state == STATE_UNINITIALIZED) {
                state = STATE_NEED_NEXT;
                return this;
            }
            final AbstractIterator duplicate = clone();
            duplicate.state = STATE_NEED_NEXT;
            return duplicate;
        }

        @Override
        public final void remove() {
            throw ContractUtils.unsupported();
        }
    }

    private final static class SkipIterator extends AbstractIterator {
        private final static int STATE_NEED_SKIP = 4;

        final Iterable source;
        final int skipCount;
        final Predicate skipFilter;

        int skipsRemaining;
        Iterator iterator;

        SkipIterator(final Iterable source, final int skipCount) {
            this.source = VerifyArgument.notNull(source, "source");
            this.skipCount = skipCount;
            this.skipFilter = null;
            this.skipsRemaining = skipCount;
        }

        SkipIterator(final Iterable source, final Predicate skipFilter) {
            this.source = VerifyArgument.notNull(source, "source");
            this.skipCount = 0;
            this.skipFilter = VerifyArgument.notNull(skipFilter, "skipFilter");
        }

        @Override
        @SuppressWarnings("CloneDoesntCallSuperClone")
        protected SkipIterator clone() {
            if (skipFilter != null) {
                return new SkipIterator<>(source, skipFilter);
            }
            return new SkipIterator<>(source, skipCount);
        }

        @Override
        public boolean hasNext() {
            switch (state) {
                case STATE_NEED_SKIP:
                    iterator = source.iterator();
                    if (skipFilter != null) {
                        while (iterator.hasNext()) {
                            final T current = iterator.next();
                            if (!skipFilter.test(current)) {
                                state = STATE_HAS_NEXT;
                                next = current;
                                return true;
                            }
                        }
                    }
                    else {
                        while (iterator.hasNext() && skipsRemaining > 0) {
                            iterator.next();
                            --skipsRemaining;
                        }
                    }
                    state = STATE_NEED_NEXT;
                    // goto case STATE_NEED_NEXT

                case STATE_NEED_NEXT:
                    if (iterator.hasNext()) {
                        state = STATE_HAS_NEXT;
                        next = iterator.next();
                        return true;
                    }
                    state = STATE_FINISHED;
                    // goto case STATE_FINISHED

                case STATE_FINISHED:
                    return false;

                case STATE_HAS_NEXT:
                    return true;
            }

            return false;
        }

        @NotNull
        @Override
        public Iterator iterator() {
            if (threadId == Thread.currentThread().getId() && state == STATE_UNINITIALIZED) {
                state = STATE_NEED_SKIP;
                return this;
            }
            final SkipIterator duplicate = clone();
            duplicate.state = STATE_NEED_SKIP;
            return duplicate;
        }
    }

    private final static class TakeIterator extends AbstractIterator {
        final Iterable source;
        final int takeCount;
        final Predicate takeFilter;

        Iterator iterator;
        int takesRemaining;

        TakeIterator(final Iterable source, final int takeCount) {
            this.source = VerifyArgument.notNull(source, "source");
            this.takeCount = takeCount;
            this.takeFilter = null;
            this.takesRemaining = takeCount;
        }

        TakeIterator(final Iterable source, final Predicate takeFilter) {
            this.source = VerifyArgument.notNull(source, "source");
            this.takeCount = Integer.MAX_VALUE;
            this.takeFilter = VerifyArgument.notNull(takeFilter, "takeFilter");
            this.takesRemaining = Integer.MAX_VALUE;
        }

        TakeIterator(final Iterable source, final int takeCount, final Predicate takeFilter) {
            this.source = VerifyArgument.notNull(source, "source");
            this.takeCount = takeCount;
            this.takeFilter = takeFilter;
            this.takesRemaining = takeCount;
        }

        @Override
        @SuppressWarnings("CloneDoesntCallSuperClone")
        protected TakeIterator clone() {
            return new TakeIterator<>(source, takeCount, takeFilter);
        }

        @Override
        public boolean hasNext() {
            switch (state) {
                case STATE_NEED_NEXT:
                    if (takesRemaining-- > 0) {
                        if (iterator == null) {
                            iterator = source.iterator();
                        }
                        if (iterator.hasNext()) {
                            final T current = iterator.next();
                            if (takeFilter == null || takeFilter.test(current)) {
                                state = STATE_HAS_NEXT;
                                next = current;
                                return true;
                            }
                        }
                    }
                    state = STATE_FINISHED;
                    // goto case STATE_FINISHED

                case STATE_FINISHED:
                    return false;

                case STATE_HAS_NEXT:
                    return true;
            }

            return false;
        }
    }

    private final static class OfTypeIterator extends AbstractIterator {
        final Iterable source;
        final Class type;

        Iterator iterator;

        OfTypeIterator(final Iterable source, final Class type) {
            this.source = VerifyArgument.notNull(source, "source");
            this.type = VerifyArgument.notNull(type, "type");
        }

        @Override
        @SuppressWarnings("CloneDoesntCallSuperClone")
        protected OfTypeIterator clone() {
            return new OfTypeIterator<>(source, type);
        }

        @Override
        @SuppressWarnings("unchecked")
        public boolean hasNext() {
            switch (state) {
                case STATE_NEED_NEXT:
                    if (iterator == null) {
                        iterator = source.iterator();
                    }
                    while (iterator.hasNext()) {
                        final T current = iterator.next();
                        if (type.isInstance(current)) {
                            state = STATE_HAS_NEXT;
                            next = (R) current;
                            return true;
                        }
                    }
                    state = STATE_FINISHED;
                    // goto case STATE_FINISHED

                case STATE_FINISHED:
                    return false;

                case STATE_HAS_NEXT:
                    return true;
            }

            return false;
        }
    }

    @SuppressWarnings("unchecked")
    private final static class WhereSelectIterableIterator extends AbstractIterator {
        final Iterable source;
        final Predicate filter;
        final Selector selector;

        Iterator iterator;

        WhereSelectIterableIterator(final Iterable source, final Predicate filter, final Selector selector) {
            this.source = VerifyArgument.notNull(source, "source");
            this.filter = filter;
            this.selector = selector;
        }

        @Override
        protected WhereSelectIterableIterator clone() {
            return new WhereSelectIterableIterator<>(source, filter, selector);
        }

        @Override
        public boolean hasNext() {
            switch (state) {
                case STATE_NEED_NEXT:
                    if (iterator == null) {
                        iterator = source.iterator();
                    }
                    while (iterator.hasNext()) {
                        final T item = iterator.next();
                        if (filter == null || filter.test(item)) {
                            next = selector != null ? selector.select(item) : (R) item;
                            state = STATE_HAS_NEXT;
                            return true;
                        }
                    }
                    state = STATE_FINISHED;

                case STATE_FINISHED:
                    return false;

                case STATE_HAS_NEXT:
                    return true;
            }
            return false;
        }

        public Iterable where(final Predicate filter) {
            if (this.selector != null) {
                return new WhereSelectIterableIterator<>(this, filter, null);
            }
            return new WhereSelectIterableIterator<>(
                this.source,
                Predicates.and((Predicate) this.filter, (Predicate) filter),
                null
            );
        }

        public  Iterable select(final Selector selector) {
            return new WhereSelectIterableIterator<>(
                this.source,
                this.filter,
                this.selector != null ? Selectors.combine(this.selector, selector)
                                      : (Selector) selector
            );
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy