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

de.unkrig.commons.util.collections.IterableUtil Maven / Gradle / Ivy


/*
 * de.unkrig.commons - A general-purpose Java class library
 *
 * Copyright (c) 2012, Arno Unkrig
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
 * following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
 *       following disclaimer in the documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
 *       products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package de.unkrig.commons.util.collections;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.atomic.AtomicInteger;

import de.unkrig.commons.lang.protocol.Predicate;
import de.unkrig.commons.lang.protocol.Transformer;
import de.unkrig.commons.nullanalysis.Nullable;

/**
 * Various {@link Iterable}-related utility methods.
 */
public final
class IterableUtil {

    private
    IterableUtil() {}

    /**
     * @return An {@link Iterable} which can't be modified through the {@link Iterator#remove()} method
     */
    public static  Iterable
    unmodifiableIterable(final Iterable i) {
        return new Iterable() {

            @Override public Iterator
            iterator() {
                final Iterator it = i.iterator();

                return new Iterator() {

                    @Override public boolean
                    hasNext() { return it.hasNext(); }

                    @Override public T
                    next() { return it.next(); }

                    @Override public void
                    remove() { throw new UnsupportedOperationException("remove"); }
                };
            }
        };
    }

    /**
     * @return An {@link Iterable} producing the  given subject n times
     */
    public static  Iterable
    repeat(final T subject, final int n) {
        if (n < 0) throw new IllegalArgumentException(Integer.toString(n));

        return new Iterable() {

            @Override public Iterator
            iterator() {
                return new Iterator() {

                    final AtomicInteger index = new AtomicInteger();

                    @Override public boolean
                    hasNext() {
                        return this.index.intValue() < n;
                    }

                    @Override public T
                    next() {
                        if (this.index.getAndIncrement() >= n) throw new NoSuchElementException();

                        return subject;
                    }

                    @Override public void
                    remove() {
                        throw new UnsupportedOperationException("remove");
                    }
                };
            }
        };
    }

    /**
     * @return An {@link Iterable} that traverses the elements of the given {@link List} in reverse order, starting
     *         with the last element of the list
     */
    public static  Iterable
    reverseList(final List list) {

        return new Iterable() {
            @Override public Iterator iterator() { return IteratorUtil.reverse(list.listIterator(list.size())); }
        };
    }

    /**
     * @return An iterator for element1 and the elements of element2
     */
    public static  Iterable
    concat(T element1, Iterable element2) {
        return IterableUtil.concat(Collections.singletonList(element1), element2);
    }

    /**
     * @return An iterator for element1 element2 and the elements of element3
     */
    public static  Iterable
    concat(T element1, T element2, Iterable element3) {
        return IterableUtil.concat(Collections.singletonList(element1), Collections.singletonList(element2), element3);
    }

    /**
     * @return An iterator for the elements of element1 and element2
     */
    public static  Iterable
    concat(Iterable element1, T... element2) {
        return IterableUtil.concat(element1, Arrays.asList(element2));
    }

    /**
     * @return An iterator for the elements of element1 and element2
     */
    public static  Iterable
    concat(Iterable element1, Iterable element2) {
        List> l = new ArrayList>(2);
        l.add(element1);
        l.add(element2);
        return IterableUtil.concat(l);
    }

    /**
     * @return An iterator for the elements of element1, element2 and element3
     */
    public static  Iterable
    concat(Iterable element1, Iterable element2, Iterable element3) {
        List> l = new ArrayList>(3);
        l.add(element1);
        l.add(element2);
        l.add(element3);
        return IterableUtil.concat(l);
    }

    /**
     * @return An iterator for the elements of element1, element2, element3 and
     *         element4
     */
    public static  Iterable
    concat(
        Iterable element1,
        Iterable element2,
        Iterable element3,
        Iterable element4
    ) {
        List> l = new ArrayList>(4);
        l.add(element1);
        l.add(element2);
        l.add(element3);
        l.add(element4);
        return IterableUtil.concat(l);
    }

    /**
     * @return An iterator for the elements of the given elements
     */
    public static  Iterable
    concat(final Iterable> elements) {

        return new Iterable() {

            @Override public Iterator
            iterator() {
                return new Iterator() {

                    Iterator> outer = elements.iterator();
                    Iterator                     inner = IteratorUtil.atEnd();

                    @Override public boolean
                    hasNext() {

                        while (!this.inner.hasNext()) {
                            if (!this.outer.hasNext()) return false;
                            this.inner = this.outer.next().iterator();
                        }

                        return true;
                    }

                    @Override public T
                    next() throws NoSuchElementException {

                        if (!this.hasNext()) throw new NoSuchElementException();

                        return this.inner.next();
                    }

                    @Override public void
                    remove() {

                        this.inner.remove();
                    }
                };
            }
        };
    }

    /**
     * Returns an {@link Iterable} which hides the elements of the delegate which do not qualifiy.
     */
    public static  Iterable
    filter(final Iterable delegate, final Predicate qualifies) {

        return new Iterable() {
            @Override public Iterator iterator() { return IteratorUtil.filter(delegate.iterator(), qualifies); }
        };
    }

    /**
     * Returns an iterable which contains the transformed elements of the delegate
     */
    public static  Iterable
    transform(final Iterable delegate, final Transformer transform) {

        return new Iterable() {
            @Override public Iterator iterator() { return IteratorUtil.transform(delegate.iterator(), transform); }
        };
    }

    /**
     * Wraps the given {@link Iterable} in a collection. As enforced by the nature of the {@link Iterable}, the only
     * supported modifying operation of the returned collection is element removal.
     *
     * @see Collection#remove(Object)
     * @see Collection#removeAll(Collection)
     * @see Collection#retainAll(Collection)
     * @see Collection#clear()
     */
    public static  Collection
    asCollection(final Iterable delegate) {

        return new AbstractCollection() {

            @Override public Iterator
            iterator() { return delegate.iterator(); }

            @Override public int
            size() {
                int result = 0;
                for (Iterator it = this.iterator(); it.hasNext(); it.next()) result++;
                return result;
            }

            @Override public boolean
            isEmpty() { return !this.iterator().hasNext(); }

            @Override public boolean
            addAll(@Nullable Collection c) { throw new UnsupportedOperationException(); }
        };
    }

    /**
     * @param   The element type of the underlying container
     * @deprecated Use {@link de.unkrig.commons.util.collections.ElementWithContext} instead
     */
    @Deprecated public interface ElementWithContext {}

    /**
     * Wraps the delegate iterable in an {@code Iterable}.
     *
     * @see ElementWithContext
     * @see IteratorUtil#iteratorWithContext(Iterator)
     */
    public static  Iterable>
    iterableWithContext(final Iterable delegate) {

        return new Iterable>() {

            @Override public Iterator>
            iterator() { return IteratorUtil.iteratorWithContext(delegate.iterator()); }
        };
    }

    /** @deprecated Use {@link IteratorUtil#iteratorWithContext(Iterator)} instead */
    @Deprecated public static  Iterator>
    iteratorWithContext(final Iterator delegate) {
        return IteratorUtil.iteratorWithContext(delegate);
    }

    /**
     * Equivalent with {@link #foR(int, int, int) foR}{@code (}start{@code ,} end{@code ,1)}.
     *
     * @see #foR(int, int, int)
     */
    public static Iterable
    foR(final int start, final int end) { return IterableUtil.foR(start, end, 1); }

    /**
     * Returns a sequence of integers which reach from start (inclusively) to end (exclusively),
     * with a step increment.
     * 

* More precise: Iff step is greater than zero, then the sequence is start, * start {@code +} step, and so forth, and ends with the last value which is less than * end. *

*

* Otherwise, iff step is less than zero, then the sequence is start, * start {@code +} step, and so forth, and ends with the last value which is greater than * end. *

*

* Otherwise, step is zero, and the returned sequence is either an * infinite sequence of values start, or, iff start {@code == } end, an empty * sequence. *

* * @throws IllegalArgumentException step {@code > 0 &&} end {@code <} start * @throws IllegalArgumentException step {@code < 0 &&} end {@code >} start */ public static Iterable foR(final int start, final int end, final int step) { return new Iterable() { @Override public Iterator iterator() { return IteratorUtil.foR(start, end, step); } }; } /** * Produces the sequence 1, 2, 3, ... {@link Integer#MAX_VALUE} */ public static final Iterable NATURALS = IterableUtil.foR(1, Integer.MAX_VALUE); /** * Produces the sequence 0, 1, 2, ... {@link Integer#MAX_VALUE} */ public static final Iterable NATURALS0 = IterableUtil.foR(0, Integer.MAX_VALUE); /** * Adds all elements of the iterable to the target collection. */ public static void addAllElementsTo(Iterable iterable, Collection target) { for (Iterator it = iterable.iterator(); it.hasNext();) target.add(it.next()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy