I am currently trying to implement Iterator which receives a collection and a char and that yields the
Strings that starts with that char.
So I ended up with the following (working) code:
class A {
public static void main (String [] args) {
String [] arr = {"abcd","gr","gres","bvg","bb"};
class FirstCharIt implements Iterator<String> {
char c;
private Iterator<String> it;
public FirstCharIt (Collection<String> lst,char c) {
this.c = c;
this.it = lst.stream().filter(x->{
return (x.charAt(0)==this.c);
}).iterator();
}
#Override
public boolean hasNext() {
return it.hasNext();
}
#Override
public String next() {
return it.next();
}
public Iterator<String> get () {
return it;
}
}
FirstCharIt it1 = new FirstCharIt(Arrays.asList(arr),'b');
for (it1.get();it1.hasNext();) {
System.out.println(it1.next());
}
}
}
Although this code is working this is not actually implementing Iterator interface and I even can remove the 'implements Iterator' from my class headline.
And of course the method get wasn't there in more right implementation
So I would like to have some advice about what I did here,
thanks
Filter the input list at initialization, have that filtered collection and an index as fields of your iterator.
Have hasNext() check if the index has reached the end of the filtered collection, and next() increase the index and return the element it previously pointed at.
static class FirstCharIt implements Iterator<String> {
private int currentIndex;
private List<String> filtered;
public FirstCharIt (List<String> coll, char letter) {
this.filtered = coll.stream().filter(x->x.startsWith(""+letter)).collect(Collectors.toList());
this.currentIndex = 0;
}
#Override
public boolean hasNext() {
return currentIndex < filtered.size();
}
#Override
public String next() {
if (!hasNext()) { throw new NoSuchElementException(); }
return filtered.get(currentIndex++);
}
}
You can try it here.
What does it mean for an iterator to be derived from a class?
More specifically, I have two classes DNode and DoublyLinkedList. DoublyLinkedList uses DNode to construct the list and I'm using both to create a stack and queue. How do I write a method which returns a class derived iterator?
Here's what I have currently:
public Iterator <E> getCollectionIterator() {
Iterator <E> i = new Iterator <E>() {
private int currentIndex = 0;
#Override
public boolean hasNext() {
return (currentIndex < size && arrayList[currentIndex] != null);
}
#Override
public E next() {
if(hasNext()) {
return arrayList[currentIndex++];
} else
throw new NoSuchElementException("Next element does not exist.");
}
#Override
public void remove() {
throw new UnsupportedOperationException("Remove not supported");
}
};
return i;
}
How do I implement a class that provides an iterator for iterating over a Doubly-LinkedList? This should be implemented as a private inner class within the Doubly-LinkedList class.
private class Iterator<T> iterator(){
for(i = 0; list.size() > 20; i++){
System.out.println("Using the iterator approach (numbers > 20) your list is: ")
}
I don't know about your Doubly-LinkedList class. But it may be something like this.
public Iterator<T> iterator() {
return new Iterator<T>() {
Node<T> node = head;
#Override
public boolean hasNext() {
return node != null;
}
#Override
public T next() {
T value = node.value;
node = node.next;
return value;
}
};
}
I have a nested collection with this representation Collection<Collection<T>>. I have implemented the Iterator on the class, but the next() method is not giving the right results. It is fetching only the first element of each list. Example List<List<String>> and values are {"1","2"},{"3","4"},{"5","6"}. The Complete layout of class.
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class NestedCollectionIterator implements Iterator<Object> {
private Collection<? extends Collection<? extends Object>> _collOfColl = null;
private Iterator<? extends Collection<? extends Object>> itCollection = null;
private Iterator<? extends Object> innerIterator = null;
Object next = null;
public NestedCollectionIterator( Collection<? extends Collection<? extends Object>> collofColl){
_collOfColl = collofColl;
itCollection = _collOfColl.iterator();
}
#Override
public boolean hasNext() {
if(itCollection.hasNext()){
innerIterator = itCollection.next().iterator();
if(innerIterator != null || innerIterator.hasNext()){
next = innerIterator.next();
return true;
}
}
return false;
}
public Object next() {
if(hasNext()){
Object obj = next;
//Need some changes here.
return obj;
}
return null;
}
#Override
public void remove() {}
}
Class to test the implementation
class Sample{
public static void main(String[] args){
List<List<String>> Nestedlist = new ArrayList<List<String>>();
List<String> l = new ArrayList<String>();
l.add("1");
l.add("2");
Nestedlist.add(l);
l = new ArrayList<String>();
l.add("3");
l.add("4");
Nestedlist.add(l);
l = new ArrayList<String>();
l.add("5");
l.add("6");
Nestedlist.add(l);
NestedCollectionIterator cc = new NestedCollectionIterator(Nestedlist);
while(cc.hasNext()){
System.out.println(cc.next.toString());
}
}
}
the results is 1,3,5. How make the list iterate over all the elements in list first and then move to next collection item inside it?
Thanks.
This one works for me - it is not generalised to Collection but there are utility methods that can give you an iterator-iterator across up to three levels of Map. I am sure you could adapt it to collections in general.
public class NestedIterator<T> implements Iterator<T> {
// Outer iterator. Goes null when exhausted.
Iterator<Iterator<T>> i2 = null;
// Inner iterator. Goes null when exhausted.
Iterator<T> i1 = null;
// Next value.
T next = null;
// Takes a depth-2 iterator.
public NestedIterator(Iterator<Iterator<T>> i2) {
this.i2 = i2;
// Prime the pump.
if (i2 != null && i2.hasNext()) {
i1 = i2.next();
}
}
#Override
public boolean hasNext() {
// Is there one waiting?
if (next == null) {
// No!
// i1 will go null if it is exhausted.
if (i1 == null) {
// i1 is exhausted! Get a new one from i2.
if (i2 != null && i2.hasNext()) {
/// Get next.
i1 = i2.next();
// Set i2 null if exhausted.
if (!i2.hasNext()) {
// Exhausted.
i2 = null;
}
} else {
// Exhausted.
i2 = null;
}
}
// A null i1 now will mean all is over!
if (i1 != null) {
if (i1.hasNext()) {
// get next.
next = i1.next();
// Set i1 null if exhausted.
if (!i1.hasNext()) {
// Exhausted.
i1 = null;
}
} else {
// Exhausted.
i1 = null;
}
}
}
return next != null;
}
#Override
public T next() {
T n = next;
next = null;
return n;
}
#Override
public void remove() {
throw new UnsupportedOperationException("Not supported.");
}
// Iterating across Maps of Maps of Maps.
static <K1, K2, K3, V> Iterator<Iterator<Iterator<V>>> iiiV(Map<K1, Map<K2, Map<K3, V>>> mapMapMap) {
final Iterator<Map<K2, Map<K3, V>>> mmi = iV(mapMapMap);
return new Iterator<Iterator<Iterator<V>>>() {
#Override
public boolean hasNext() {
return mmi.hasNext();
}
#Override
public Iterator<Iterator<V>> next() {
return iiV(mmi.next());
}
#Override
public void remove() {
mmi.remove();
}
};
}
// Iterating across Maps of Maps.
static <K1, K2, V> Iterator<Iterator<V>> iiV(Map<K1, Map<K2, V>> mapMap) {
final Iterator<Map<K2, V>> mi = iV(mapMap);
return new Iterator<Iterator<V>>() {
#Override
public boolean hasNext() {
return mi.hasNext();
}
#Override
public Iterator<V> next() {
return iV(mi.next());
}
#Override
public void remove() {
mi.remove();
}
};
}
// Iterating across Map values.
static <K, V> Iterator<V> iV(final Map<K, V> map) {
return iV(map.entrySet().iterator());
}
// Iterating across Map.Entries.
static <K, V> Iterator<V> iV(final Iterator<Map.Entry<K, V>> mei) {
return new Iterator<V>() {
#Override
public boolean hasNext() {
return mei.hasNext();
}
#Override
public V next() {
return mei.next().getValue();
}
#Override
public void remove() {
mei.remove();
}
};
}
}
Design an iterator for a collection of collections in java. The iterator should hide the nesting, allowing you to iterate all of the elements belonging to all of the collections as if you were working with a single collection
This is an old question, but nowadays (2019) we have JDK8+ goodies. In particular, we have streams, which make this task straightforward:
public static <T> Iterator<T> flatIterator(Collection<Collection<T>> collections) {
return collections.stream()
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.iterator();
}
I'm filtering null inner collections out, just in case...
EDIT: If you also want to filter null elements out of the inner collections, just add an extra non-null filter aflter flatMap:
return collections.stream()
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.filter(Objects::nonNull)
.iterator();
Here is a possible implementation. Note that I left remove() unimplemented:
public class MultiIterator <T> implements Iterator<T>{
private Iterator<? extends Collection<T>> it;
private Iterator<T> innerIt;
private T next;
private boolean hasNext = true;
public MultiIterator(Collection<? extends Collection<T>> collections) {
it = collections.iterator();
prepareNext();
}
private void prepareNext() {
do {
if (innerIt == null || !innerIt.hasNext()) {
if (!it.hasNext()) {
hasNext = false;
return;
} else
innerIt = it.next().iterator();
}
} while (!innerIt.hasNext());
next = innerIt.next();
}
#Override
public boolean hasNext() {
return hasNext;
}
#Override
public T next() {
if (!hasNext)
throw new NoSuchElementException();
T res = next;
prepareNext();
return res;
}
#Override
public void remove() {
//TODO
}
}
In this post you can see two implementations, the only (minor) difference is that it takes an iterator of iterators instead of a collection of collections.
This difference combined with the requirement to iterate the elements in a round-robin fashion (a requirement that wasn't requested by the OP in this question) adds the overhead of copying the iterators into a list.
The first approach is lazy: it will iterate an element only when this element is requested, the 'price' we have to pay is that the code is more complex because it needs to handle more edge-cases:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
public class MultiIterator<E> implements Iterator {
List<Iterator<E>> iterators = new LinkedList<>();
Iterator<E> current = null;
public MultiIterator(Iterator<Iterator<E>> iterator) {
// copy the iterators into a list
while (iterator.hasNext()) {
iterators.add(iterator.next());
}
}
#Override
public boolean hasNext() {
boolean result = false;
if (iterators.isEmpty() && (current == null || !current.hasNext())) {
return false;
}
if (current == null) {
current = iterators.remove(0);
}
while (!current.hasNext() && !iterators.isEmpty()) {
current = iterators.remove(0);
}
if (current.hasNext()) {
result = true;
}
return result;
}
#Override
public E next() {
if (current == null) {
try {
current = iterators.remove(0);
} catch (IndexOutOfBoundsException e) {
throw new NoSuchElementException();
}
}
E result = current.next(); // if this method was called without checking 'hasNext' this line might raise NoSuchElementException which is fine
iterators.add(current);
current = iterators.remove(0);
return result;
}
// test
public static void main(String[] args) {
List<Integer> a = new LinkedList<>();
a.add(1);
a.add(7);
a.add(13);
a.add(17);
List<Integer> b = new LinkedList<>();
b.add(2);
b.add(8);
b.add(14);
b.add(18);
List<Integer> c = new LinkedList<>();
c.add(3);
c.add(9);
List<Integer> d = new LinkedList<>();
d.add(4);
d.add(10);
d.add(15);
List<Integer> e = new LinkedList<>();
e.add(5);
e.add(11);
List<Integer> f = new LinkedList<>();
f.add(6);
f.add(12);
f.add(16);
f.add(19);
List<Iterator<Integer>> iterators = new LinkedList<>();
iterators.add(a.iterator());
iterators.add(b.iterator());
iterators.add(c.iterator());
iterators.add(d.iterator());
iterators.add(e.iterator());
iterators.add(f.iterator());
MultiIterator<Integer> it = new MultiIterator<>(iterators.iterator());
while (it.hasNext()) {
System.out.print(it.next() + ","); // prints: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
}
}
}
and the second ('greedy' copying of all the elements from all the iterators in the requested order into a list and returning an iterator to that list ):
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class MultiIterator<E> {
Iterator<Iterator<E>> iterator = null;
List<E> elements = new LinkedList<>();
private MultiIterator(Iterator<Iterator<E>> iterator) {
this.iterator = iterator;
}
private void copyElementsInOrder() {
List<Iterator<E>> iterators = new LinkedList<>();
// copy the iterators into a list
while (iterator.hasNext()) {
iterators.add(iterator.next());
}
// go over the list, round-robin, and grab one
// element from each sub-iterator and add it to *elements*
// empty sub-iterators will get dropped off the list
while (!iterators.isEmpty()) {
Iterator<E> subIterator = iterators.remove(0);
if (subIterator.hasNext()) {
elements.add(subIterator.next());
iterators.add(subIterator);
}
}
}
public static <E> Iterator<E> iterator(Iterator<Iterator<E>> iterator) {
MultiIterator<E> instance = new MultiIterator<>(iterator);
instance.copyElementsInOrder();
return instance.elements.iterator();
}
// test
public static void main(String[] args) {
List<Integer> a = new LinkedList<>();
a.add(1);
a.add(7);
a.add(13);
a.add(17);
List<Integer> b = new LinkedList<>();
b.add(2);
b.add(8);
b.add(14);
b.add(18);
List<Integer> c = new LinkedList<>();
c.add(3);
c.add(9);
List<Integer> d = new LinkedList<>();
d.add(4);
d.add(10);
d.add(15);
List<Integer> e = new LinkedList<>();
e.add(5);
e.add(11);
List<Integer> f = new LinkedList<>();
f.add(6);
f.add(12);
f.add(16);
f.add(19);
List<Iterator<Integer>> iterators = new LinkedList<>();
iterators.add(a.iterator());
iterators.add(b.iterator());
iterators.add(c.iterator());
iterators.add(d.iterator());
iterators.add(e.iterator());
iterators.add(f.iterator());
Iterator<Integer> it = MultiIterator.<Integer>iterator(iterators.iterator());
while (it.hasNext()) {
System.out.print(it.next() + ","); // prints: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
}
}
}
I included a simple 'test' code in order to show the way to use the MultiIterator, this is not always trivial (because of the use of Generics) as you can see on the line:
Iterator<Integer> it = MultiIterator.<Integer>iterator(iterators.iterator());
Here is another implementation:
import java.util.Iterator;
import java.util.NoSuchElementException;
import static java.util.Collections.emptyIterator;
public class Multiterator<E> implements Iterator<E> {
private Iterator<Iterator<E>> root;
private Iterator<E> current;
public Multiterator(Iterator<Iterator<E>> root) {
this.root = root;
current = null;
}
#Override
public boolean hasNext() {
if (current == null || !current.hasNext()) {
current = getNextNonNullOrEmpty(root);
}
return current.hasNext();
}
private Iterator<E> getNextNonNullOrEmpty(Iterator<Iterator<E>> root) {
while (root.hasNext()) {
Iterator<E> next = root.next();
if (next != null && next.hasNext()) {
return next;
}
}
return emptyIterator();
}
#Override
public E next() {
if (current == null) {
throw new NoSuchElementException();
}
return current.next();
}
}
First, take a look at the implementation of the iterator in java.util.LinkedList
http://www.docjar.com/html/api/java/util/LinkedList.java.html
From there your task is easy just implement a single iterator that takes into account the fact that it is iterating over collections.
Regards.
if all you have to work with is the java Iterator: which just have hasNext(), next() and remove(), i figured you have to go around it.
Process it as you will process a 2D array, that is, with an outer and inner loop, because they have same "arrangement" but different datatype. As you process, you transfer them to a new collection.
so maybe a private method:
private void convertToSingleCollection()
{
while("column")
{
//convert the "column" to an arra
for( "Row")
{
//add to newCollection here
}
//remove the processed column from CollectionOFcollection
}
}
//call the above method in your constructor
public iterator<T> Iterator()
{
newCollection.iterator();
}
public boolean hasNext()
{
return Iterator().hasNext()
}
public T next()
{
if(!hasNext())
{
//exception message or message
}
else
//return "next"
}
end
I hope this helps. There should be other ways to solve it i guess.