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 extends T> i) {
return new Iterable() {
@Override public Iterator
iterator() {
final Iterator extends T> 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 extends T> 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 extends T> 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 extends T> 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 extends T> element1, Iterable extends T> 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 extends T> element1, Iterable extends T> element2, Iterable extends T> 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 extends T> element1,
Iterable extends T> element2,
Iterable extends T> element3,
Iterable extends T> 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 extends Iterable extends T>> elements) {
return new Iterable() {
@Override public Iterator
iterator() {
return new Iterator() {
Iterator extends Iterable extends T>> outer = elements.iterator();
Iterator extends T> 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 extends T> delegate, final Predicate super T> 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 extends I> delegate, final Transformer super I, ? extends O> 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 extends T> 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 extends T> 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 extends T> 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 super T> target) {
for (Iterator it = iterable.iterator(); it.hasNext();) target.add(it.next());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy