Return-Path: X-Original-To: apmail-commons-commits-archive@minotaur.apache.org Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 9AA06186D0 for ; Wed, 27 May 2015 21:18:20 +0000 (UTC) Received: (qmail 15774 invoked by uid 500); 27 May 2015 21:18:20 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 15703 invoked by uid 500); 27 May 2015 21:18:20 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 15694 invoked by uid 99); 27 May 2015 21:18:20 -0000 Received: from eris.apache.org (HELO hades.apache.org) (140.211.11.105) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 27 May 2015 21:18:20 +0000 Received: from hades.apache.org (localhost [127.0.0.1]) by hades.apache.org (ASF Mail Server at hades.apache.org) with ESMTP id 4FF0CAC06F7 for ; Wed, 27 May 2015 21:18:20 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1682121 - in /commons/proper/collections/trunk/src/main/java/org/apache/commons/collections4: FluentIterable.java IterableUtils.java iterators/ZippingIterator.java Date: Wed, 27 May 2015 21:18:20 -0000 To: commits@commons.apache.org From: tn@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20150527211820.4FF0CAC06F7@hades.apache.org> 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 implement } /** + * Returns a new FluentIterable whose iterator will traverse the + * elements of the current and provided iterable in natural order. + *

+ * Example: natural ordering + *

    + *
  • this contains elements [1, 3, 5, 7] + *
  • other contains elements [2, 4, 6, 8] + *
+ *

+ * The returned iterable will traverse the elements in the following + * order: [1, 2, 3, 4, 5, 6, 7, 8] + *

+ * A null 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 collate(final Iterable 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. + *

+ * Example: descending order + *

    + *
  • this contains elements [7, 5, 3, 1] + *
  • other contains elements [8, 6, 4, 2] + *
+ *

+ * The returned iterable will traverse the elements in the following + * order: [8, 7, 6, 5, 4, 3, 2, 1] + *

+ * A null 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 collate(final Iterable other, Comparator 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 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 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 implement public FluentIterable 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 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 zip(final Iterable... others) { + @SuppressWarnings("unchecked") + Iterable[] 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 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. *

- * 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. + *

+ * The returned iterable's iterator supports {@code remove()} when the corresponding + * input iterator supports it. + * + * @param 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 Iterable collatedIterable(final Iterable a, + final Iterable b, + final Comparator comparator) { + return new FluentIterable() { + @Override + public Iterator 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 Iterable filteredIterable(final Iterable iterable, final Predicate predicate) { + public static Iterable filteredIterable(final Iterable iterable, + final Predicate 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. + *

+ * 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. + *

+ * The returned iterable's iterator supports {@code remove()} if the + * provided iterable is a {@link List} instance. + * + * @param the element type + * @param iterable the iterable to use, may be null + * @return a reversed view of the specified iterable + * @see ReverseListIterator + */ + public static Iterable reversedIterable(final Iterable iterable) { + return new FluentIterable() { + @Override + public Iterator iterator() { + final List list = (iterable instanceof List) ? + (List) iterable : + IteratorUtils.toList(emptyIteratorIfNull(iterable)); + + return new ReverseListIterator(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 Iterable transformedIterable(final Iterable iterable, final Transformer transformer) { + public static Iterable transformedIterable(final Iterable iterable, + final Transformer 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. + *

+ * 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. + *

+ * The returned iterable's iterator supports {@code remove()} when the corresponding + * input iterator supports it. + * + * @param 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 Iterable zippingIterable(final Iterable a, final Iterable b) { + return zippingIterable(new Iterable[] {a, b}); + } + + /** + * Interleaves two iterables into a single iterable. + *

+ * 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. + *

+ * The returned iterable's iterator supports {@code remove()} when the corresponding + * input iterator supports it. + * + * @param the element type + * @param a the first iterable + * @param b the second iterable + * @return a new iterable, interleaving the provided iterables + */ + public static Iterable zippingIterable(final Iterable... iterables) { + return new FluentIterable() { + @Override + public Iterator iterator() { + @SuppressWarnings("unchecked") + Iterator[] iterators = new Iterator[iterables.length]; + for (int i = 0; i < iterables.length; i++) { + iterators[i] = emptyIteratorIfNull(iterables[i]); + } + return new ZippingIterator(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. + *

+ * Given two {@link Iterator} instances A and + * B, the {@link #next} method on this iterator will + * alternate between A.next() and B.next(). + * + * @since 4.1 + * @version $Id$ + */ +public class ZippingIterator implements Iterator { + + /** The {@link Iterator}s to evaluate. */ + private final Iterator> iterators; + /** The next iterator to use for next(). */ + private Iterator nextIterator = null; + /** The last iterator which was used for next(). */ + private Iterator lastReturned = null; + + // Constructors + // ---------------------------------------------------------------------- + + /** + * Constructs a new ZippingIterator 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 a, final Iterator b) { + this(new Iterator[] {a, b}); + } + + /** + * Constructs a new ZippingIterator 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... iterators) { + // create a mutable list + final List> list = new ArrayList>(); + for (Iterator 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 true 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 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