2010-04-19 44 views
8

Tengo un bucle y la estructura como esta:¿Es posible hacer que un método se ejecute solo una vez?

for(....) 
.... 
.... 
if(isTrue) 
... do something.. 
.. method to be executed once (doTrick) is declared outside for loop. 
....endif 
endfor 

public void doTrick() 
... 
... 
..end 

¿Es posible que un método en el bucle que se ejecuta sólo una vez?

+0

¿cuál es la diferencia? –

+1

All-caps implica que es un acrónimo, que no lo es. –

+0

@Gandalf No es un acrónimo sino un nombre para que no lo escriba en mayúscula –

Respuesta

31

seguro ..

if(!alreadyExecuted) { 
    doTrick(); 
    alreadyExecuted = true; 
} 
+17

En un entorno multiproceso, es posible que desee sincronizar ese bloque. – extraneon

+0

Probablemente, aunque the alreadyExecuted va a ser una variable local, – vickirk

2

quizás la palabra clave break es lo que necesita? Después de ejecutar su método, llame al descanso; Lo siento, no es 100% claro lo que quieres decir con tu pregunta.

Tener una mirada here a partir de los documentos de sol

+0

Un descanso terminaría inmediatamente el ciclo for-loop. Como el ciclo contiene más código, que solo el método-llamada, supongo que no se pretende un corte. – Mnementh

4

puede evitar el if() mediante el uso de este truco:

private Runnable once; 
private final static Runnable NOP = new Runnable() { 
    public void run() { 
     // Do nothing 
    } 
} 

public void method() { 
    once = new Runnable() { 
     public void run() { 
      doTrick(); 
      once = NOP; 
     } 
    } 

    for (...) { 
     ... 
     once.run(); 
     ... 
    } 
} 
+0

Eso funcionaría, pero es un poco exagerado, ¿no? La respuesta de Rosdi es mucho más simple/clara. – vickirk

+0

-1 ¿Por qué querrías evitar el if()? – Tomas

+7

@Tomas: para ampliar su horizonte :-) –

1

Otra solución exageración:

Dependiendo de lo que quiera hacer, podría ser posible usar un bloque de inicialización estático.

public class YourKlass{ 
    public void yourMethod(){ 

     DoTrick trick; 

     for(int i = 0; condition; i++){ 
      // ... (1) 
      trick = new DoTrick(); // or any kind of accessing DoTrick 
      // ... (2) 
     } 

    } 
} 

public class DoTrick{ 
    static{ 
     // Whatever should be executed only once 
    } 
} 

solución simple:

O, en vez lo que desea es ejecutar la primera parte fuera del bucle:

int i = 0; 
if(condition){ 
    // ... (1) 
    // do trick 
    // ... (2) 
} 
for(i = 1; condition; i++){ 
    // ... (1) 
    // ... (2) 
} 
+0

-1 La primera solución es exagerada, la segunda solución no está en el ciclo. – Tomas

1
import java.util.ArrayList; 

class RemoveDuplicate { 
    public static void main(String[] args) { 
     ArrayList<String> originalList = new ArrayList<String>(); 
     originalList.add("foo"); 
     originalList.add("bar"); 
     originalList.add("bat"); 
     originalList.add("baz"); 
     originalList.add("bar"); 
     originalList.add("bar"); 
     String str="bar"; 
     ArrayList<String> duplicateList = new ArrayList<String>(); 

     // adding duplicates to duplicateList 
     for(String currentString : originalList) { 
     if(currentString.startsWith(str)) { 
       duplicateList.add(currentString); 
      } 
     } 
     // removing duplicates in duplicatesList 
     for(String removeString : duplicateList) { 
      originalList.remove(removeString); 
     } 
     // finally adding duplicateElement 
     originalList.add(str); 

     for(String currEntry : originalList) { 
      System.out.println(currEntry); 
     } 
    } 
} 
+0

¿Cómo se relaciona esto con la pregunta? –

0

mi muestra de mi aplicación:

boolean alreadyExecuted = false; 

a continuación:

private void startMyService() { 

    if(!alreadyExecuted) { 

     final Handler handler = new Handler(); 
     handler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
      //Do something after 4 seconds 
       context.startService(new Intent(context, myService.class)); 
       alreadyExecuted = true; 
      } 
     }, 4000); 
     } 
2

En Java 8, se puede hacer efectiva esta usando memoization automática como se describe aquí: Do it in Java 8: Automatic memoization

Admito que memoization podría ser considerado excesivo para un escenario de "ejecutar una vez", pero es una alternativa bastante limpia a algunos descritos en respuestas anteriores.

Por ejemplo:

public void doSomething() { ... } 

Map<Boolean, Boolean> cache = new ConcurrentHashMap<>(); 

public void doSomethingOnce() { 
    cache.computeIfAbsent(true, x -> { 
    doSomething(); 
    return true; 
    }); 
} 
2

Su puede utilizar AtomicBoolean para asegurarse de que la tarea sólo se llama la primera vez:

public class Once { 
    private AtomicBoolean done = new AtomicBoolean(); 

    public void run(Runnable task) { 
     if (done.get()) return; 
     if (done.compareAndSet(false, true)) { 
      task.run(); 
     } 
    } 
} 

Uso:

Once once = new Once(); 
once.run(new Runnable() { 
    @Override 
    public void run() { 
     foo(); 
    } 
}); 

// or java 8 
once.run(() -> foo()); 
Cuestiones relacionadas