Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Collections-699 PairingIterator #74

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
/*
* 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.Iterator;
import java.util.NoSuchElementException;
import java.util.Objects;
import org.apache.commons.collections4.iterators.PairingIterator.Entry;

/**
* Provides an iteration over the elements of two iterators. It will be return a
* {@link Entry} containing the child iterators elements.
* <p>
* Given two {@link Iterator} instances {@code A} and {@code B}. The
* {@link #next()} method will return a {@link Entry} with the elements of the
* {@code A} and {@code B} as values of the {@link Entry} until both iterators
* are exhausted.
* </p>
* <p>
* If one of the iterators is null, the result {@link Entry} contains also a
* null values until both child iterators exhausted.
* </p>
* <p>
* If one iterator has more elements then the other, the result {@link Entry}
* will contain a null value and the value of the not empty child iterator until
* both of the iterator exhausted.
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are missing a close tag for 'p' here.

* @param <F> type of first value. The first value of {@link Entry}
*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blank line is not needed.

* @param <S> type of second value. The second value of {@link Entry}
*
* @since 4.4
*/
public class PairingIterator<F, S> implements Iterator<Entry<F, S>> {

private final Iterator<F> firstIterator;
private final Iterator<S> secondIterator;

/**
* Constructs a new <code>PairingIterator</code> that will provide a
* {@link Entry} containing the child iterator elements.
*
* @param firstIterator the first iterator
* @param secondIterator the second iterator
*/
public PairingIterator(Iterator<F> firstIterator, Iterator<S> secondIterator) {
this.firstIterator = firstIterator;
this.secondIterator = secondIterator;
}

/**
* Returns {@code true} if one of the child iterators has remaining elements.
*/
@Override
public boolean hasNext() {
return (null != firstIterator && firstIterator.hasNext())
|| (null != secondIterator && secondIterator.hasNext());
}

/**
* Returns the next {@link Entry} with the next values of the child iterators.
*
* @return a {@link Entry} with the next values of child iterators
* @throws NoSuchElementException if no child iterator has any more elements
*/
@Override
public Entry<F, S> next() throws NoSuchElementException {
if (!hasNext()) {
throw new NoSuchElementException();
}
final F firstValue = null != firstIterator && firstIterator.hasNext() ? firstIterator.next() : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not seem necessary to call each delegate iterator's hasNext() method since this method just invoked its own hasNext().

In general, this begs the question of what thread-safety guarantees this class makes. If none, the Javadocs should say so.

final S secondValue = null != secondIterator && secondIterator.hasNext() ? secondIterator.next() : null;
return new Entry<F, S>(firstValue, secondValue);
}

/**
* Removes the last returned values of the child iterators.
*/
@Override
public void remove() {
if (firstIterator != null) {
firstIterator.remove();
}
if (secondIterator != null) {
secondIterator.remove();
}
}

/**
* Contains two values of different generic types.
*
* @param <F> the type of the first element
* @param <S> the type of the second element
*/
public static class Entry<F, S> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not needed if you reuse one of:

  • org.apache.commons.collections4.keyvalue.DefaultKeyValue<K, V>
  • org.apache.commons.collections4.keyvalue.DefaultMapEntry<K, V>
  • org.apache.commons.collections4.keyvalue.MultiKey<K>

private final F firstValue;
private final S secondValue;

/**
* Constructs a new {@link Entry} of two generic values.
*
* @param firstValue the first value
* @param secondValue the second value
*/
Entry(F firstValue, S secondValue) {
this.firstValue = firstValue;
this.secondValue = secondValue;
}

/**
* Returns the first value.
*
* @return the first value
*/
public F getFirstValue() {
return firstValue;
}

/**
* Returns the second value.
*
* @return the second value
*/
public S getSecondValue() {
return secondValue;
}

@Override
public int hashCode() {
return Objects.hash(firstValue, secondValue);
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Entry other = (Entry) obj;
return Objects.equals(firstValue, other.firstValue) && Objects.equals(secondValue, other.secondValue);
}

@Override
public String toString() {
return "Entry [firstValue=" + firstValue + ", secondValue=" + secondValue + "]";
}

}

}
Loading