2015-02-24 7 views
7

Non ho trovato alcun argomento a riguardo. Voglio sapere se è sicuro di cambiare il riferimento per la classe lista durante un ciclo come quello sotto:Riferimento oggetto elenco modificato durante il ciclo Java

Tree minimalTree = someTree; 
for (Tree st : minimalTree.getSubtrees()) { 
    if (condition) 
    minimalTree = st; 
} 

Condivide l'iteratore ottiene la risistemazione e riparte per il nuovo riferimento?

Modifica: Ho dimenticato di dire: questo codice è adatto per le situazioni in cui voglio restringere la ricerca di elementi nell'albero, diciamo, l'albero più piccolo che contiene determinati elementi. In questo caso, sarebbe più veloce continuare a cercare solo le strutture interne di "minimalTree" anziché l'intera struttura "someTree".

+1

cosa succede quando si prova? –

+0

Probabilmente dovresti usare una chiamata ricorsiva per quello. – biziclop

+0

Sembrava funzionare bene fino ad ora, ma non sono sicuro che funzionerà per un'elaborazione massiccia. Ma forse @biziclop ha ragione e questo tipo di codifica dovrebbe essere evitato ... –

risposta

6

No, l'iterazione non verrà ripristinata. Secondo il JLS:

La maggiore per la dichiarazione equivale ad una base per la dichiarazione di forma:

for (I #i = Expression.iterator(); #i.hasNext();) { 
    {VariableModifier} TargetType Identifier = (TargetType) #i.next(); 
    Statement 
} 

La definizione rende evidente che l'iteratore viene inizializzato solo una volta, prima di la prima iterazione del ciclo.

Il comportamento durante l'iterazione su un array con un'istruzione enhanced for è simile in questo senso.

Tuttavia personalmente lo considero una pratica scarsa in quanto rende il codice difficile da capire.

2

In realtà, ci sono due domande:

Voglio sapere se è sicuro di cambiare il riferimento per la classe lista durante un ciclo come quello sotto:

Sì, è salvo. E per sicurezza intendo: cambiare il riferimento non interferisce con il ciclo già in esecuzione.

L'iteratore si reimposta e ricomincia per il nuovo riferimento?

No, l'iteratore non viene mai ripristinato. Sarebbe esattamente l'opposto della sicurezza.

A mio parere, non è una buona pratica modificare iteratore o variabili di raccolta all'interno di un ciclo. Rende il codice più difficile da capire e probabilmente il risultato non è quello che ti aspetti quando lo fai (come nel tuo caso ho capito che ti aspettavi che il ciclo ricominciasse a rivalutare la collezione).

Nel tuo caso, incapsulare in un metodo e ricorsivamente chiamano il sotto-albero:

Tree findMinimalTree(Tree tree) { 
    for (Tree st : tree.getSubtrees()) { 
    if (condition) 
     return findMinimalTree(st); 
    } 
    return tree; 
} 
+0

Non sono d'accordo. Leggi la risposta di biziclop. Nelle mie parole, minimalTree.getSubtrees() [. Iterator()] viene valutato esattamente una volta quando si entra nel ciclo. Successivamente, puoi lasciare puntare il riferimento a MinimumTree a ciò che desideri. Tieni a mente l'asserzione minimalTree = st non modifica l'oggetto a cui si fa riferimento in precedenza con minimalTree (cosa che C++ farebbe qui). Cambia solo il minimo di riferimento, i. e. l'oggetto minimalTree punta a. – fjf2002

+0

Sì, capisco il tuo punto di vista. Secondo me il problema è (i) che a prima vista sembra funzionare come la controparte C++, e (ii) quando esegui il debug non riesci più a vedere la collezione su cui stai iterando. –

+0

"Sembra funzionare" non è il modo appropriato per esprimere questo, cercherò di migliorarlo. Eventuali suggerimenti? –