2011-03-02 13 views
18

Estoy intentando implementar un método de búsqueda en un TreeSet. Al usar un iterador con una condición, me gustaría poder ejecutar el conjunto e imprimir el objeto que coincida con la condición. Sin embargo, la forma en que lo estoy haciendo en este momento es imprimir el objeto subsiguiente en lugar de la actual. Esto es lo que tengo hasta ahora:¿Cómo me refiero al objeto actual en un iterador?

public void getDetails() { 
     Iterator<Person> it = this.getPersonSet().iterator(); 
     System.out.println("Enter First Name"); 
     String first = in.next().toLowerCase(); 
     System.out.println("Enter Second Name"); 
     String last = in.next().toLowerCase(); 

     while (it.hasNext()) { 
      if (it.next().getLast().toLowerCase().equals(last)) { 
       Person p = it.next(); 
       System.out.println(p); 
      } 
     } 

    } 

Cualquier ayuda sería grande

Respuesta

24

Esto es lo que se quiere hacer:

while (it.hasNext()) { 
      Person p = it.next(); 
      if (p.getLast().toLowerCase().equals(last)) { 
       System.out.println(p); 
      } 
     } 
+0

Muchas gracias, el clavo :) – Robairto

+0

¿Esto se salte el primer objeto en el ArrayList? :/ –

+1

@SrujanBarai - no. (Literalmente sí ... que se "lo saltes") –

1

Mantenga la referencia del objeto en una separada var:

Person current = it.next(); 
current.methodOne(); 
current.methodTwo(); 

Cuando haya terminado con el valor actual, volver a evaluarlo el próximo

... 
// done? 
current = it.next(); 

En un bucle parece:

while(it.hasNext()) { 
    Person current = it.next(); 
    current.doA(); 
    current.doB(); 
    current.doC(); 
} 
21

¿Cómo refiero al objeto actual en un iterador

Para el registro, la API Iterator no le permiten para hacer esto. No hay noción de un objeto "actual". El método Iterator.next() le proporciona el siguiente objeto ... y continúa.

(Los métodos ListIterator.previous() y ListIterator.next() son análogos. Nótese que en el caso ListIterator, el comportamiento método se documenta en términos de un cursor que indica una posición antes de/entre/después de los elementos de la secuencia que está siendo iterados.)

La solución es asignar el resultado de llamar al it.next() a una variable temporal, como se describe en la respuesta aceptada.


No sé con certeza por qué los diseñadores no incluyen la noción de un objeto "actual" en la API, pero puedo pensar en un par de razones:

  • Se haría un objeto iterador típico más grande; es decir, un campo extra para contener el objeto actual.
  • Significaría más 1 método más para que una clase Iterator lo implemente.
  • La noción de un objeto actual no encaja bien con el modelo de "cursor" documentado en la interfaz ListIterator ... y está implícito en el diseño actual Iterator.
  • Existe un problema menor de que el iterador "se aferre" al objeto actual, lo que impide que sea GC.
  • La gran mayoría de los casos de uso de iteradores no requieren un objeto actual.
  • Hay otras maneras de lidiar con esto.

Suena como una buena llamada ...

+0

No entiendo para nada por qué no hay "corriente". Un uso muy básico de esto es cualquier caso en el que uno quiera comparar el valor actual y el siguiente de forma asincrónica. Por ejemplo, si se modifica una lista, es posible que el índice ya no apunte al lugar donde se desea, por lo que la solución obvia es un iterador ... aunque eso no permite la comparación de valores. Ergio. – Thumbz

+0

@Thumbz - Bueno ... ver mi respuesta por razones por las cuales "actual" sería una mala idea en general. (Sería malo romper algunos casos de uso solo por conveniencia de otros). Y para su caso de uso, considere escribir una clase contenedora de iteradores que agregue un método getCurrent() ... si eso simplifica las cosas para usted. –

+3

Si mira el código fuente de un iterador, nada de la segunda parte de su respuesta es verdadero. Un iterador contiene 2 variables: 'int cursor' apuntando al siguiente elemento y' int lastRet' apuntando al último elemento devuelto. Por lo tanto, no se necesita campo adicional. Estos son números de índice y no los objetos en sí mismos, por lo tanto, un iterador no se 'cuelga' en modo alguno del objeto actual. El modelo de cursor se usa para explicar el diseño del iterador, y no al revés. Y no es porque el 90% no lo use, no tiene que implementarlo. Eso es solo un mal diseño. – Didii

0

Si necesita una implementación existente, puede usar las de Google Guava o Apache Commons Collections.
Las otras respuestas son más fáciles para su sencillo problema, pero si usted necesita para pasar el iterador alrededor y no perder de vista el último elemento devuelto por next(), éstas ayudarían.

Aquí está un ejemplo usando la guayaba con el código de la OP (assumging Person de hecho tiene un método String toLowerCase()):

import com.google.common.collect.PeekingIterator; 
import static com.google.common.collect.Iterators.peekingIterator; 

public void getDetails() { 
    PeekingIterator<Person> it = peekingIterator(this.getPersonSet().iterator()); 
    System.out.println("Enter First Name"); 
    String first = in.next().toLowerCase(); 
    System.out.println("Enter Second Name"); 
    String last = in.next().toLowerCase(); 

    while (it.hasNext()) { 
     // note the usage of peek() instead of next() 
     if (it.peek().getLast().toLowerCase().equals(last)) { 
      Person p = it.next(); 
      System.out.println(p); 
     } 
    } 

} 
+0

Sería mejor mostrar un pequeño ejemplo de cómo esos iteradores se pueden utilizar en este caso específico en lugar de simplemente vincularlos. –

Cuestiones relacionadas