You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by tn...@apache.org on 2015/05/27 23:18:20 UTC
svn commit: r1682121 - in
/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4:
FluentIterable.java IterableUtils.java iterators/ZippingIterator.java
Author: tn
Date: Wed May 27 21:18:19 2015
New Revision: 1682121
URL: http://svn.apache.org/r1682121
Log:
Add collating, zipping, reversing methods to FluentIterable, add ZippingIterator.
Added:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java (with props)
Modified:
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/FluentIterable.java
commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IterableUtils.java
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/FluentIterable.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/FluentIterable.java?rev=1682121&r1=1682120&r2=1682121&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/FluentIterable.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/FluentIterable.java Wed May 27 21:18:19 2015
@@ -18,6 +18,7 @@ package org.apache.commons.collections4;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Comparator;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
@@ -152,6 +153,55 @@ public class FluentIterable<E> implement
}
/**
+ * Returns a new FluentIterable whose iterator will traverse the
+ * elements of the current and provided iterable in natural order.
+ * <p>
+ * Example: natural ordering
+ * <ul>
+ * <li>this contains elements [1, 3, 5, 7]
+ * <li>other contains elements [2, 4, 6, 8]
+ * </ul>
+ * <p>
+ * The returned iterable will traverse the elements in the following
+ * order: [1, 2, 3, 4, 5, 6, 7, 8]
+ * <p>
+ * A <code>null</code> iterable will be treated as an empty iterable.
+ *
+ * @param other the other iterable to collate, may be null
+ * @return a new iterable, collating this iterable with the other in natural order
+ * @see {@link org.apache.commons.collections4.iterators.CollatingIterator CollatingIterator}
+ */
+ public FluentIterable<E> collate(final Iterable<E> other) {
+ return of(IterableUtils.collatedIterable(iterable, other, null));
+ }
+
+ /**
+ * Returns a new FluentIterable whose iterator will traverse the
+ * elements of the current and provided iterable according to the
+ * ordering defined by an comparator.
+ * <p>
+ * Example: descending order
+ * <ul>
+ * <li>this contains elements [7, 5, 3, 1]
+ * <li>other contains elements [8, 6, 4, 2]
+ * </ul>
+ * <p>
+ * The returned iterable will traverse the elements in the following
+ * order: [8, 7, 6, 5, 4, 3, 2, 1]
+ * <p>
+ * A <code>null</code> iterable will be treated as an empty iterable.
+ *
+ * @param other the other iterable to collate, may be null
+ * @param comparator the comparator to define an ordering, may be null,
+ * in which case natural ordering will be used
+ * @return a new iterable, collating this iterable with the other in natural order
+ * @see {@link org.apache.commons.collections4.iterators.CollatingIterator CollatingIterator}
+ */
+ public FluentIterable<E> collate(final Iterable<E> other, Comparator<? super E> comparator) {
+ return of(IterableUtils.collatedIterable(iterable, other, comparator));
+ }
+
+ /**
* This method fully traverses an iterator of this iterable and returns
* a new iterable with the same contents, but without any reference
* to the originating iterables and/or iterators.
@@ -203,6 +253,16 @@ public class FluentIterable<E> implement
}
/**
+ * Returns a new FluentIterable whose iterator will traverse the
+ * elements from this iterable in reverse order.
+ *
+ * @return a new iterable, providing a reversed view of this iterable
+ */
+ public FluentIterable<E> reverse() {
+ return of(IterableUtils.reversedIterable(iterable));
+ }
+
+ /**
* Returns a new FluentIterable whose iterator will skip the first
* N elements from this iterable.
*
@@ -236,7 +296,36 @@ public class FluentIterable<E> implement
public FluentIterable<E> unique() {
return of(IterableUtils.uniqueIterable(iterable));
}
-
+
+ /**
+ * Returns a new FluentIterable whose iterator will traverse
+ * the elements of this iterable and the provided elements in
+ * alternating order.
+ *
+ * @param elements the elements to interleave
+ * @return a new iterable, interleaving this iterable with the elements
+ */
+ @SuppressWarnings("unchecked")
+ public FluentIterable<E> zip(final E... elements) {
+ return zip(Arrays.asList(elements));
+ }
+
+ /**
+ * Returns a new FluentIterable whose iterator will traverse
+ * the elements of this iterable and the other iterable in
+ * alternating order.
+ *
+ * @param other the other iterable to interleave
+ * @return a new iterable, interleaving this iterable with others
+ */
+ public FluentIterable<E> zip(final Iterable<E>... others) {
+ @SuppressWarnings("unchecked")
+ Iterable<E>[] iterables = new Iterable[1 + others.length];
+ iterables[0] = iterable;
+ System.arraycopy(others, 0, iterables, 1, others.length);
+ return of(IterableUtils.zippingIterable(iterables));
+ }
+
// convenience methods
// ----------------------------------------------------------------------
@@ -357,10 +446,10 @@ public class FluentIterable<E> implement
}
/**
- * Returns a list containing all elements of this iterable by traversing
- * its iterator.
+ * Returns a list containing all elements of this iterable by
+ * traversing its iterator.
* <p>
- * The returned list is mutable.
+ * The returned list is guaranteed to be mutable.
*
* @return a list of the iterable contents
*/
Modified: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IterableUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IterableUtils.java?rev=1682121&r1=1682120&r2=1682121&view=diff
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IterableUtils.java (original)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/IterableUtils.java Wed May 27 21:18:19 2015
@@ -17,11 +17,14 @@
package org.apache.commons.collections4;
import java.util.Collection;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.collections4.iterators.LazyIteratorChain;
+import org.apache.commons.collections4.iterators.ReverseListIterator;
import org.apache.commons.collections4.iterators.UniqueFilterIterator;
+import org.apache.commons.collections4.iterators.ZippingIterator;
/**
* Provides utility methods and decorators for {@link Iterable} instances.
@@ -136,6 +139,37 @@ public class IterableUtils {
};
}
+ // Collated
+ // ----------------------------------------------------------------------
+
+ /**
+ * Combines the two provided iterables into an ordered iterable using the
+ * provided comparator. If the comparator is null, natural ordering will be
+ * used.
+ * <p>
+ * The returned iterable's iterator supports {@code remove()} when the corresponding
+ * input iterator supports it.
+ *
+ * @param <E> the element type
+ * @param a the first iterable, may be null
+ * @param b the second iterable, may be null
+ * @param comparator the comparator defining an ordering over the elements,
+ * may be null, in which case natural ordering will be used
+ * @return a filtered view on the specified iterable
+ */
+ public static <E> Iterable<E> collatedIterable(final Iterable<E> a,
+ final Iterable<E> b,
+ final Comparator<? super E> comparator) {
+ return new FluentIterable<E>() {
+ @Override
+ public Iterator<E> iterator() {
+ return IteratorUtils.collatedIterator(comparator,
+ emptyIteratorIfNull(a),
+ emptyIteratorIfNull(b));
+ }
+ };
+ }
+
// Filtered
// ----------------------------------------------------------------------
@@ -151,7 +185,8 @@ public class IterableUtils {
* @return a filtered view on the specified iterable
* @throws NullPointerException if predicate is null
*/
- public static <E> Iterable<E> filteredIterable(final Iterable<E> iterable, final Predicate<? super E> predicate) {
+ public static <E> Iterable<E> filteredIterable(final Iterable<E> iterable,
+ final Predicate<? super E> predicate) {
if (predicate == null) {
throw new NullPointerException("predicate must not be null.");
}
@@ -232,6 +267,38 @@ public class IterableUtils {
};
}
+ // Reversed
+ // ----------------------------------------------------------------------
+
+ /**
+ * Returns a reversed view of the given iterable.
+ * <p>
+ * In case the provided iterable is a {@link List} instance, a
+ * {@link ReverseListIterator} will be used to reverse the traversal
+ * order, otherwise an intermediate {@link List} needs to be
+ * created.
+ * <p>
+ * The returned iterable's iterator supports {@code remove()} if the
+ * provided iterable is a {@link List} instance.
+ *
+ * @param <E> the element type
+ * @param iterable the iterable to use, may be null
+ * @return a reversed view of the specified iterable
+ * @see ReverseListIterator
+ */
+ public static <E> Iterable<E> reversedIterable(final Iterable<E> iterable) {
+ return new FluentIterable<E>() {
+ @Override
+ public Iterator<E> iterator() {
+ final List<E> list = (iterable instanceof List<?>) ?
+ (List<E>) iterable :
+ IteratorUtils.toList(emptyIteratorIfNull(iterable));
+
+ return new ReverseListIterator<E>(list);
+ }
+ };
+ }
+
// Skipping
// ----------------------------------------------------------------------
@@ -276,7 +343,8 @@ public class IterableUtils {
* @return a transformed view of the specified iterable
* @throws NullPointerException if transformer is null
*/
- public static <I, O> Iterable<O> transformedIterable(final Iterable<I> iterable, final Transformer<? super I, ? extends O> transformer) {
+ public static <I, O> Iterable<O> transformedIterable(final Iterable<I> iterable,
+ final Transformer<? super I, ? extends O> transformer) {
if (transformer == null) {
throw new NullPointerException("transformer must not be null.");
}
@@ -309,6 +377,58 @@ public class IterableUtils {
}
};
}
+
+ // Zipping
+ // ----------------------------------------------------------------------
+
+ /**
+ * Interleaves two iterables into a single iterable.
+ * <p>
+ * The returned iterable has an iterator that traverses the elements in {@code a}
+ * and {@code b} in alternating order. The source iterators are not polled until
+ * necessary.
+ * <p>
+ * The returned iterable's iterator supports {@code remove()} when the corresponding
+ * input iterator supports it.
+ *
+ * @param <E> the element type
+ * @param a the first iterable
+ * @param b the second iterable
+ * @return a new iterable, interleaving the provided iterables
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> Iterable<E> zippingIterable(final Iterable<E> a, final Iterable<E> b) {
+ return zippingIterable(new Iterable[] {a, b});
+ }
+
+ /**
+ * Interleaves two iterables into a single iterable.
+ * <p>
+ * The returned iterable has an iterator that traverses the elements in {@code a}
+ * and {@code b} in alternating order. The source iterators are not polled until
+ * necessary.
+ * <p>
+ * The returned iterable's iterator supports {@code remove()} when the corresponding
+ * input iterator supports it.
+ *
+ * @param <E> the element type
+ * @param a the first iterable
+ * @param b the second iterable
+ * @return a new iterable, interleaving the provided iterables
+ */
+ public static <E> Iterable<E> zippingIterable(final Iterable<E>... iterables) {
+ return new FluentIterable<E>() {
+ @Override
+ public Iterator<E> iterator() {
+ @SuppressWarnings("unchecked")
+ Iterator<E>[] iterators = new Iterator[iterables.length];
+ for (int i = 0; i < iterables.length; i++) {
+ iterators[i] = emptyIteratorIfNull(iterables[i]);
+ }
+ return new ZippingIterator<E>(iterators);
+ }
+ };
+ }
// Utility methods
// ----------------------------------------------------------------------
Added: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java
URL: http://svn.apache.org/viewvc/commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java?rev=1682121&view=auto
==============================================================================
--- commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java (added)
+++ commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java Wed May 27 21:18:19 2015
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.commons.collections4.iterators;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.commons.collections4.FluentIterable;
+
+/**
+ * Provides an interleaved iteration over the elements contained in a
+ * collection of Iterators.
+ * <p>
+ * Given two {@link Iterator} instances <code>A</code> and
+ * <code>B</code>, the {@link #next} method on this iterator will
+ * alternate between <code>A.next()</code> and <code>B.next()</code>.
+ *
+ * @since 4.1
+ * @version $Id$
+ */
+public class ZippingIterator<E> implements Iterator<E> {
+
+ /** The {@link Iterator}s to evaluate. */
+ private final Iterator<Iterator<? extends E>> iterators;
+ /** The next iterator to use for next(). */
+ private Iterator<? extends E> nextIterator = null;
+ /** The last iterator which was used for next(). */
+ private Iterator<? extends E> lastReturned = null;
+
+ // Constructors
+ // ----------------------------------------------------------------------
+
+ /**
+ * Constructs a new <code>ZippingIterator</code> that will provide
+ * interleaved iteration over the two given iterators.
+ *
+ * @param a the first child iterator
+ * @param b the second child iterator
+ * @throws NullPointerException if either iterator is null
+ */
+ @SuppressWarnings("unchecked")
+ public ZippingIterator(final Iterator<? extends E> a, final Iterator<? extends E> b) {
+ this(new Iterator[] {a, b});
+ }
+
+ /**
+ * Constructs a new <code>ZippingIterator</code> that will use the
+ * specified comparator to provide ordered iteration over the array of
+ * iterators.
+ *
+ * @param iterators the array of iterators
+ * @throws NullPointerException if iterators array is or contains null
+ */
+ public ZippingIterator(final Iterator<? extends E>... iterators) {
+ // create a mutable list
+ final List<Iterator<? extends E>> list = new ArrayList<Iterator<? extends E>>();
+ for (Iterator<? extends E> iterator : iterators) {
+ if (iterator == null) {
+ throw new NullPointerException("Iterator must not be null");
+ }
+ list.add(iterator);
+ }
+ this.iterators = FluentIterable.of(list).loop().iterator();
+ }
+
+ // Iterator Methods
+ // -------------------------------------------------------------------
+
+ /**
+ * Returns <code>true</code> if any child iterator has remaining elements.
+ *
+ * @return true if this iterator has remaining elements
+ */
+ public boolean hasNext() {
+ // the next iterator has already been determined
+ // this might happen if hasNext() was called multiple
+ if (nextIterator != null) {
+ return true;
+ }
+
+ while(iterators.hasNext()) {
+ final Iterator<? extends E> iterator = iterators.next();
+ if (iterator.hasNext()) {
+ nextIterator = iterator;
+ return true;
+ } else {
+ // iterator is exhausted, remove it
+ iterators.remove();
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the next element from a child iterator.
+ *
+ * @return the next interleaved element
+ * @throws NoSuchElementException if no child iterator has any more elements
+ */
+ public E next() throws NoSuchElementException {
+ if (!hasNext()) {
+ throw new NoSuchElementException();
+ }
+
+ final E val = nextIterator.next();
+ lastReturned = nextIterator;
+ nextIterator = null;
+ return val;
+ }
+
+ /**
+ * Removes the last returned element from the child iterator that produced it.
+ *
+ * @throws IllegalStateException if there is no last returned element, or if
+ * the last returned element has already been removed
+ */
+ public void remove() {
+ if (lastReturned == null) {
+ throw new IllegalStateException("No value can be removed at present");
+ }
+ lastReturned.remove();
+ lastReturned = null;
+ }
+
+}
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java
------------------------------------------------------------------------------
svn:keywords = Id Revision HeadURL
Propchange: commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4/iterators/ZippingIterator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain