Можно ли заставить метод выполняться только один раз? - PullRequest
11 голосов
/ 19 апреля 2010

У меня есть цикл for и структура, подобная этой:

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

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

Возможно ли, чтобы метод в цикле for выполнялся только один раз?

Ответы [ 8 ]

40 голосов
/ 19 апреля 2010

Конечно! ..

if(!alreadyExecuted) {
    doTrick();
    alreadyExecuted = true;
}
8 голосов
/ 25 июля 2017

Вы можете использовать AtomicBoolean, чтобы убедиться, что задача вызывается только в первый раз:

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

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

Использование:

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

// or java 8
once.run(() -> foo());
5 голосов
/ 19 апреля 2010

Вы можете избежать if(), используя этот трюк:

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();
        ...
    }
}
3 голосов
/ 31 мая 2017

В Java 8 вы можете эффективно сделать это, используя автоматическое запоминание, как описано здесь: Сделайте это в Java 8: автоматическое запоминание

Я признаю, что запоминание можно считать излишним для сценария "однократного запуска", но это довольно чистая альтернатива некоторым, описанным в предыдущих ответах.

Например:

public void doSomething() { ... }

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

public void doSomethingOnce() {
  cache.computeIfAbsent(true, x -> {
    doSomething();
    return true;
  });
}
2 голосов
/ 19 апреля 2010

Еще одно решение для излишков:

В зависимости от того, что вы хотите сделать, может быть возможно использовать статический блок инициализации.

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

Простое решение:

Или вместо этого вы просто хотите выполнить первую часть вне цикла:

int i = 0;
if( condition ){
    // ... (1)
    // do trick
    // ... (2)
}
for(i = 1; condition; i++){
    // ... (1)
    // ... (2)
}
2 голосов
/ 19 апреля 2010

возможно ключевое слово break - это то, что вам нужно? После запуска вы вызываете метод break; Я сожалею, что не на 100% ясно, что вы имеете в виду из вашего вопроса.

Взгляните здесь от солнца документы

1 голос
/ 20 декабря 2012
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 голосов
/ 15 июня 2015

мой образец из моего приложения:

boolean alreadyExecuted = false;

тогда:

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);
       }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...