2011-03-02 15 views
18

Sto tentando di implementare un metodo di ricerca in un TreeSet. Usando un iteratore con un conditional mi piacerebbe essere in grado di correre attraverso il set e stampare l'oggetto che corrisponde alla condizione. Tuttavia, il modo in cui lo sto facendo al momento sta stampando l'oggetto successivo anziché la corrente. Questo è quello che ho finora:Come fare riferimento all'oggetto corrente in un iteratore

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

    } 

Qualsiasi aiuto sarebbe grande

risposta

24

Questo è ciò che si vorrebbe fare:

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

Grazie mille, punto sul :) – Robairto

+0

Sarà questo non saltare il primo oggetto nella ArrayList? :/ –

+1

@SrujanBarai - no. (Letteralmente sì ... non "salterà") –

1

Tenere il riferimento dell'oggetto in un separato var:

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

Quando hai finito con il valore corrente, riassociare il prossimo

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

In un ciclo assomiglia:

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

Come posso fare riferimento all'oggetto corrente in un iteratore

Per la cronaca, l'API Iterator non consente di per fare questo. Non c'è idea di un oggetto "attuale". Il metodo Iterator.next() ti dà l'oggetto successivo ... e si sposta.

(I ListIterator.previous() e ListIterator.next() metodi sono analoghi. Si noti che nel caso ListIterator, comportamento metodo è documentato in termini di un cursore che indica una posizione prima/tra/dopo elementi nella sequenza essendo iterato.)

La soluzione è assegnare il risultato di chiamare it.next() a una variabile temporanea, come descritto dalla risposta accettata.


Non so per certo perché i progettisti non hanno incluso la nozione di un oggetto "corrente" in API, ma mi viene in mente un paio di motivi:

  • E ' renderebbe un tipico oggetto iteratore più grande; vale a dire un campo in più per contenere l'oggetto corrente.
  • Significherebbe più 1 metodo per implementare una classe Iterator.
  • La nozione di oggetto corrente non si adatta bene al modello "cursore" documentato nell'interfaccia ListIterator ... e implicito nell'attuale versione Iterator.
  • C'è un problema minore di Iterator "aggrappato" all'oggetto corrente, impedendo quindi che venga eseguito da GC.
  • La maggior parte dei casi di utilizzo di iteratore non richiede un oggetto corrente.
  • Ci sono altri modi per affrontare questo.

Suona come una buona chiamata ...

+0

Non capisco perché non ci sia "corrente". Un uso molto basilare di questo è ogni caso in cui si vorrebbe confrontare il valore corrente e il successivo in modo asincrono. Ad esempio, se una lista viene modificata, l'indice potrebbe non puntare più a dove lo si desidera, quindi la soluzione ovvia è un iteratore ... anche se ciò non consente il confronto dei valori. Erg. – Thumbz

+0

@Thumbz - Beh ... vedi la mia risposta per i motivi per cui "corrente" sarebbe una cattiva idea in generale. (Sarebbe male rompere alcuni casi d'uso solo per comodità degli altri.) E per il tuo caso d'uso, considera la scrittura di una classe wrapper iteratore che aggiunge un metodo getCurrent() ... se questo semplifica le cose per te. –

+3

Se guardi il codice sorgente di un iteratore, nulla della seconda parte della tua risposta è vero. Un iteratore contiene 2 variabili: 'cursor cursore' che punta all'elemento successivo e' int lastRet' che punta all'ultimo elemento restituito. Pertanto non è necessario alcun campo aggiuntivo. Questi sono numeri di indice e non gli oggetti stessi, quindi un iteratore non si blocca in alcun modo sull'oggetto corrente. Il modello del cursore viene utilizzato per spiegare il design dell'iteratore, non il contrario. E non è perché il 90% non lo userebbe, non è necessario implementarlo. Questo è solo cattivo design. – Didii

0

Se è necessaria un'implementazione esistente, è possibile utilizzare quelli da Google Guava o Apache Commons Collections.
Le altre risposte sono più facili per il tuo semplice problema, ma se hai bisogno di passare l'iteratore e di tenere traccia dell'ultimo elemento restituito da next(), ciò sarebbe di aiuto.

Ecco un esempio utilizzando Guava con il codice del PO (assumging Person anzi ha un metodo 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

Sarebbe meglio mostrare un piccolo esempio di come quegli iteratori possano essere usati in questo caso specifico invece di limitarsi a collegarli. –

Problemi correlati