1

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.

5
  • 4
    Well currently your "implementation" of the Iterator interface is just going to say that you haven't got any elements. What have you tried, and what happened? ("is not giving the right results" is not enough information.) Commented Oct 3, 2013 at 16:06
  • How many levels do you have? Just 1? Commented Oct 3, 2013 at 16:06
  • Well, return null; does not seem right, I agree. But what is the quesiton? I tried to implement Please try harder, as just adding some fields, but otherwise leaving the generated methods untouched as they are is not much of "implementing"... Commented Oct 3, 2013 at 16:06
  • 1
    You'll learn a lot more if you post the code (along with describing the problem in sufficient detail) and we tell you what you did wrong, rather than us just giving a solution from scratch. This just also happens to be required for Stack Overflow questions. Commented Oct 3, 2013 at 16:09
  • I have updated the code and question. Please check Commented Oct 3, 2013 at 23:13

1 Answer 1

1

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();
      }
    };
  }

}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.