2010-07-24 19 views
7

Diseñe un iterador para una colección de colecciones en java. El iterador debe ocultar el agrupamiento, lo que le permite iterar todos los elementos que pertenecen a todas las colecciones como si estuviera trabajando con una sola colecciónEntrevista: diseñe un iterador para una colección de colecciones

+0

¿Qué hay para * design *? ¿El Prototipo? ¿La implementación? –

+0

ambos, ¿cuál es la interfaz y cómo la implementarías? –

+2

Si esta es su entrevista de trabajo, ¿por qué la publica aquí en lugar de solo hacerlo? – Jasper

Respuesta

1

Aquí hay una posible implementación. Tenga en cuenta que dejé remove() sin aplicarse:

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 
    } 

} 
+1

Su solución no tiene en cuenta los valores nulos en la colección de colecciones dada. Solución: en prepareNext(), el bucle interno debe continuar hasta que it.next() no sea nulo antes de hacerlo it.next(). Iterator(), y debe rescatar si no queda ningún objeto de colección no nulo para nosotros para usar. – Kowshik

0

Primero, observe la implementación del iterador en java.util. ListaEnlazada

http://www.docjar.com/html/api/java/util/LinkedList.java.html

a partir de ahí su tarea es fácil sólo aplicar un único repetidor que tiene en cuenta el hecho de que está interactuando sobre colecciones.

Atentamente.

+0

¿Por qué se bajó este valor? –

0

si todo lo que tiene que trabajar con es el iterador Java: que acaban de hasNext(), next() y remove(), me di cuenta de que tiene que dar la vuelta eso.

Procéselo como se va a procesar una matriz 2D, es decir, con un bucle externo e interno, porque tienen la misma "disposición" pero diferente tipo de datos. A medida que procesa, los transfiere a una nueva colección.

así que tal vez un método privado:

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" 
    } 

final

espero que esto ayude. Debería haber otras formas de resolverlo, supongo.

1

En this post puede ver dos implementaciones, la única (menor) diferencia es que toma un iterador de iteradores en lugar de una colección de colecciones.

Esta diferencia se combina con el requisito para recorrer los elementos de un round-robin (un requisito que no fue solicitada por el PO en este pregunta) añade la sobrecarga de copiar los iteradores en una lista.

El primer enfoque es perezosa: va a recorrer un elemento sólo cuando se solicita este elemento, el 'precio' que tenemos que pagar es que el código es más complejo ya que tiene que manejar más de borde casos:

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, 
     } 
    } 
} 

y el segundo (copia 'codicioso' de todos los elementos de todos los iteradores en el orden solicitado en una lista y devuelve un iterador a esa lista):

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, 
     } 
    } 
} 

que incluía un simple 'prueba' código para mostrar la manera de usar el MultiIterator, esto no siempre trivial (debido al uso de Generics) como se puede ver en la línea:

Iterator<Integer> it = MultiIterator.<Integer>iterator(iterators.iterator()); 
Cuestiones relacionadas