patternjavaMinor
CombinedIterable for Java
Viewed 0 times
combinediterableforjava
Problem
This class combines multiple instances of
```
package net.coderodde.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* This class implements an {@code Iterable} combining multiple
* {@code Iterable}s into one.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 11, 2016)
* @param the actual type of elements being iterated.
*/
public class CombinedIterable implements Iterable {
private final Iterator[] iterators;
public static Iterable combine(Iterable... iterables) {
return new CombinedIterable(iterables);
}
private CombinedIterable(Iterable... iterables) {
this.iterators = new Iterator[iterables.length];
for (int i = 0; i iterator() {
return new MultiIterator();
}
private final class MultiIterator implements Iterator {
private int index;
private Iterator lastReadIterator;
MultiIterator() {
if (iterators.length > 0) {
this.lastReadIterator = (Iterator) iterators[0];
}
}
@Override
public boolean hasNext() {
while (index ) iterators[index];
T element = lastReadIterator.next();
if (!iterators[index].hasNext()) {
++index;
}
return element;
}
@Override
public void remove() {
lastReadIterator.remove();
}
}
public static void main(String[] args) {
List list1 = new ArrayList<>();
List list2 = new LinkedList<>();
Set set = new LinkedHashSet<>();
for (int i = 10; i emptySet = Collections.emptySet();
List emptyList = Collectio
Iterable into one and iterates through them in the order they are given to CombinedIterable. CombinedIterable.java:```
package net.coderodde.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;
/**
* This class implements an {@code Iterable} combining multiple
* {@code Iterable}s into one.
*
* @author Rodion "rodde" Efremov
* @version 1.6 (Feb 11, 2016)
* @param the actual type of elements being iterated.
*/
public class CombinedIterable implements Iterable {
private final Iterator[] iterators;
public static Iterable combine(Iterable... iterables) {
return new CombinedIterable(iterables);
}
private CombinedIterable(Iterable... iterables) {
this.iterators = new Iterator[iterables.length];
for (int i = 0; i iterator() {
return new MultiIterator();
}
private final class MultiIterator implements Iterator {
private int index;
private Iterator lastReadIterator;
MultiIterator() {
if (iterators.length > 0) {
this.lastReadIterator = (Iterator) iterators[0];
}
}
@Override
public boolean hasNext() {
while (index ) iterators[index];
T element = lastReadIterator.next();
if (!iterators[index].hasNext()) {
++index;
}
return element;
}
@Override
public void remove() {
lastReadIterator.remove();
}
}
public static void main(String[] args) {
List list1 = new ArrayList<>();
List list2 = new LinkedList<>();
Set set = new LinkedHashSet<>();
for (int i = 10; i emptySet = Collections.emptySet();
List emptyList = Collectio
Solution
Your code has a lot of warnings that can be avoided.
-
You should never use raw types, like in the following
and
-
You should not create array of a generic type but prefer to use a
This is fragile and leads to a lot of unnecessary warnings in your code, because you need to explicitely cast afterwards, like in:
Instead, what you want is to declare
also you can retrieve an iterator from that list with just
-
The type
-
The method
A side-note in your
is not necessary since the method
-
You should never use raw types, like in the following
return new CombinedIterable(iterables); // use CombinedIterable<> insteadand
return new MultiIterator(); // use MultiIterator<> instead-
You should not create array of a generic type but prefer to use a
List.this.iterators = new Iterator[iterables.length];This is fragile and leads to a lot of unnecessary warnings in your code, because you need to explicitely cast afterwards, like in:
lastReadIterator = (Iterator) iterators[index];Instead, what you want is to declare
iterators as a List>. This way, you can use an enhanced for loop to loop through the iterable to add each of their iterator to the list.private final List> iterators;
private CombinedIterable(Iterable... iterables) {
this.iterators = new ArrayList<>(iterables.length);
for (Iterable iterable : iterables) {
this.iterators.add(iterable.iterator());
}
}also you can retrieve an iterator from that list with just
lastReadIterator = iterators.get(index);-
The type
T of MultiIterator is hiding the type T of CombinedIterable. Since MultiIterator is an internal helper class, it actually does not need to be typed: it can reuse the type of the enclosing CombinedIterable, with:private final class MultiIterator implements Iterator { /* ... */ }-
The method
combine and the constructor CombinedIterable both take a vararg of a generic type, which leads a warning because of a potential heap pollution. If you know this won't happen, you can annotate the method with @SafeVarargs and remove the warning. It also documents that the method does not perform potentially unsafe operation on the varargs parameter.A side-note in your
next() method: the following block of codeif (!iterators.get(index).hasNext()) {
++index;
}is not necessary since the method
hasNext() will have already set the index to the next iterator to read from. As such, you can safely remove it.Code Snippets
return new CombinedIterable(iterables); // use CombinedIterable<> insteadreturn new MultiIterator(); // use MultiIterator<> insteadthis.iterators = new Iterator[iterables.length];lastReadIterator = (Iterator<T>) iterators[index];private final List<Iterator<T>> iterators;
private CombinedIterable(Iterable<T>... iterables) {
this.iterators = new ArrayList<>(iterables.length);
for (Iterable<T> iterable : iterables) {
this.iterators.add(iterable.iterator());
}
}Context
StackExchange Code Review Q#119622, answer score: 4
Revisions (0)
No revisions yet.