Skip to content

Commit

Permalink
Merge a9012fc into 7d8b979
Browse files Browse the repository at this point in the history
  • Loading branch information
anantdamle committed May 29, 2021
2 parents 7d8b979 + a9012fc commit 88012d4
Show file tree
Hide file tree
Showing 7 changed files with 542 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/main/java/org/apache/commons/collections4/IterableUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import org.apache.commons.collections4.functors.EqualPredicate;
import org.apache.commons.collections4.iterators.LazyIteratorChain;
import org.apache.commons.collections4.iterators.PairedIterator.PairedItem;
import org.apache.commons.collections4.iterators.ReverseListIterator;
import org.apache.commons.collections4.iterators.UniqueFilterIterator;

Expand Down Expand Up @@ -554,6 +555,34 @@ public Iterator<E> iterator() {
};
}

/**
* Provides iteration over the elements contained in a pair of Iterables in-tandem.
* <p>
* The returned iterable has an iterator that traverses the elements in {@code a}
* and {@code b} together until one of the iterables is traversed completely.
* <p>
* The returned iterable's iterator does NOT support {@code remove()}.
*
* @param <L> the left elements' type
* @param <R> the right elements' type
* @param left the iterable for the left side elements
* @param right the iterable for the right side elements
* @return an iterable, over the decorated iterables to traverse them together until one is
* exhausted
* @throws NullPointerException if any iterator is null
*/
public static <L, R> Iterable<PairedItem<L, R>> pairedIterable(final Iterable<L> left, final Iterable<R> right) {
checkNotNull(left);
checkNotNull(right);

return new FluentIterable<PairedItem<L, R>>(){
@Override
public Iterator<PairedItem<L, R>> iterator() {
return IteratorUtils.pairedIterator(left.iterator(), right.iterator());
}
};
}

// Utility methods
// ----------------------------------------------------------------------

Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/apache/commons/collections4/IteratorUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.apache.commons.collections4.iterators.ObjectArrayIterator;
import org.apache.commons.collections4.iterators.ObjectArrayListIterator;
import org.apache.commons.collections4.iterators.ObjectGraphIterator;
import org.apache.commons.collections4.iterators.PairedIterator;
import org.apache.commons.collections4.iterators.PeekingIterator;
import org.apache.commons.collections4.iterators.PushbackIterator;
import org.apache.commons.collections4.iterators.SingletonIterator;
Expand Down Expand Up @@ -907,6 +908,20 @@ public static <E> ZippingIterator<E> zippingIterator(final Iterator<? extends E>
return new ZippingIterator<>(iterators);
}

/**
* Returns an iterator that provides the elements contained in a pair of Iterators.
*
* @param <L> the left elements' type
* @param <R> the right elements' type
* @param left the iterator for the left side elements
* @param right the iterator for the right side elements
* @return an iterator, to iterate over the decorated iterators together until one is exhausted
* @throws NullPointerException if any iterator is null
*/
public static <L, R> PairedIterator<L, R> pairedIterator(final Iterator<L> left, Iterator<R> right) {
return PairedIterator.of(left, right);
}

// Views
//-----------------------------------------------------------------------
/**
Expand Down
100 changes: 100 additions & 0 deletions src/main/java/org/apache/commons/collections4/PairedIterable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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;

import java.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.apache.commons.collections4.iterators.PairedIterator;
import org.apache.commons.collections4.iterators.PairedIterator.PairedItem;

/**
* Provides iteration over the elements contained in a pair of Iterables in-tandem.
*
* <p>
* Given two {@link Iterable} instances {@code A} and {@code B}, the {@link #iterator} method on this
* iterator provide a Pair of {@code A.next()} and {@code B.next()} until one of the iterators is
* exhausted.
* </p>
* This can simplify zipping over two iterables using the for-each construct.
* Example usage:
* <pre>{@code
* List<Integer> studentIds = ...
* List<String> studentNames = ...
*
* for (PairedItem<Integer, String> items : PairedIterable.of(studentIds, studentNames) {
* Integer studentId = item.getLeft();
* String studentName = item.getRight();
* ...
* }
* }</pre>
*
* @param <L> the left elements' type
* @param <R> the right elements' type
*/
public class PairedIterable<L, R> implements Iterable<PairedItem<L, R>> {

/**
* The left {@link Iterable}s to evaluate.
*/
private final Iterable<L> leftIterable;

/**
* The right {@link Iterable}s to evaluate.
*/
private final Iterable<R> rightIterable;

// Constructor
// ----------------------------------------------------------------------

/**
* Constructs a new {@code PairedIterable} that will provide iteration over two given iterables.
*
* @param leftIterable the iterable for the left side element.
* @param rightIterable the iterable for the right side element.
* @throws NullPointerException if either iterator is null
*/
public PairedIterable(Iterable<L> leftIterable, Iterable<R> rightIterable) {
this.leftIterable = leftIterable;
this.rightIterable = rightIterable;
}

/**
* Convenience static factory to construct the PairedIterable from provided
* {@link Iterable} sources.
*
* @param leftIterable the iterable for the left side element.
* @param rightIterable the iterable for the right side element.
* @return the Iterable to iterate over the elements derived from the provided iterables.
* @throws NullPointerException if either iterables is null
*/
public static <L, R> PairedIterable<L, R> of(Iterable<L> leftIterable, Iterable<R> rightIterable) {
return new PairedIterable<>(leftIterable, rightIterable);
}

// Iterable Methods
// -------------------------------------------------------------------

@Override
public Iterator<PairedItem<L, R>> iterator() {
return PairedIterator.ofIterables(leftIterable, rightIterable);
}

public Stream<PairedItem<L, R>> stream() {
return StreamSupport.stream(spliterator(), /*parallel=*/ false);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* 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 static java.util.Objects.requireNonNull;

import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.commons.collections4.iterators.PairedIterator.PairedItem;

/**
* Provides a iteration over the elements contained in a pair of Iterators.
*
* <p>
* Given two {@link Iterator} instances {@code A} and {@code B}, the {@link #next} method on this
* iterator provide a Pair of {@code A.next()} and {@code B.next()} until one of the iterators is
* exhausted.
* </p>
* Example usage:
* <pre>{@code
* List<Integer> studentIds = ...
* List<String> studentNames = ...
*
* PairedIterator<PairedItem<Integer, String>> pairedIterator =
* PairedIterator.ofIterables(studentIds, studentNames);
*
* while (pairedIterator.hasNext()) {
* PairedItem<Integer, String> item = zippedIterator.next();
* ...
* }
* }</pre>
*
* @param <L> the left elements' type
* @param <R> the right elements' type
*/
public class PairedIterator<L, R> implements Iterator<PairedItem<L, R>> {

/**
* The left {@link Iterator}s to evaluate.
*/
private final Iterator<L> leftIterator;

/**
* The right {@link Iterator}s to evaluate.
*/
private final Iterator<R> rightIterator;

// Constructor
// ----------------------------------------------------------------------

/**
* Constructs a new {@code ZipPairIterator} that will provide iteration over the two given
* iterators.
*
* @param leftIterator the iterator for the left side element.
* @param rightIterator the iterator for the right side element.
* @throws NullPointerException if either iterator is null
*/
public PairedIterator(Iterator<L> leftIterator, Iterator<R> rightIterator) {
this.leftIterator = requireNonNull(leftIterator);
this.rightIterator = requireNonNull(rightIterator);
}

/**
* Convenience static factory to construct the ZipPairIterator
*
* @param leftIterator the iterator for the left side element.
* @param rightIterator the iterator for the right side element.
* @return the iterator to iterate over the provided iterators.
* @throws NullPointerException if either iterator is null
*/
public static <L, R> PairedIterator<L, R> of(Iterator<L> leftIterator, Iterator<R> rightIterator) {
return new PairedIterator<>(leftIterator, rightIterator);
}

/**
* Convenience static factory to construct the ZipPairIterator from any {@link Iterable} sources.
*
* @param leftIterable the iterable for the left side element.
* @param rightIterable the iterable for the right side element.
* @return the iterator to iterate over the iterators derived from the provided iterables.
* @throws NullPointerException if either iterables is null
*/
public static <L, R> PairedIterator<L, R> ofIterables(Iterable<L> leftIterable, Iterable<R> rightIterable) {
return of(requireNonNull(leftIterable).iterator(), requireNonNull(rightIterable).iterator());
}

// Iterator Methods
// -------------------------------------------------------------------

/**
* Returns {@code true} if both the child iterators have remaining elements.
*
* @return true if both the child iterators have remaining elements
*/
@Override
public boolean hasNext() {
return leftIterator.hasNext() && rightIterator.hasNext();
}

/**
* Returns the next elements from both the child iterators.
*
* @return the next elements from both the iterators.
* @throws NoSuchElementException if any one child iterator is exhausted.
*/
@Override
public PairedItem<L, R> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}

return PairedItem.of(leftIterator.next(), rightIterator.next());
}

/**
* An immutable tuple class to represent elements from both the iterators.
*
* @param <L> the left elements' type
* @param <R> the right elements' type
*/
public static final class PairedItem<L, R> {

private final L leftItem;

private final R rightItem;

private PairedItem(L leftItem, R rightItem) {
this.leftItem = leftItem;
this.rightItem = rightItem;
}

/**
* Convenience static factory method to construct the tuple pair.
*
* @param left the left element
* @param right the right element
* @return the Immutable tuple pair of two elements.
*/
private static <L, R> PairedItem<L, R> of(L left, R right) {
return new PairedItem<>(left, right);
}

public L getLeftItem() {
return leftItem;
}

public R getRightItem() {
return rightItem;
}

@Override
public String toString() {
return String.format("{%s, %s}", leftItem, rightItem);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1421,4 +1421,12 @@ public void testZippingIterator() {
assertTrue(IteratorUtils.zippingIterator(ie, ie, ie) instanceof ZippingIterator, "create instance fail");
assertTrue(IteratorUtils.zippingIterator(ie, ie) instanceof ZippingIterator, "create instance fail");
}

@Test
public void testPairedIterator() {
final ArrayList<String> stringList = new ArrayList<>();
final ArrayList<Integer> integerList = new ArrayList<>();

assertTrue(IteratorUtils.pairedIterator(stringList.iterator(), integerList.iterator()) instanceof PairedIterator, "create instance failed");
}
}

0 comments on commit 88012d4

Please sign in to comment.