0

I have a variable oneTimeTask. Its type is:

Optional<Runnable> oneTimeTask=...;

Do you think this example is a dirty way to 'reset' the Optional<Runnable>:

oneTimeTask = Optional.of(() ->  {
            /*Run task
            ...*/
            oneTimeTask= Optional.empty();
        });

... what do you think?

oneTimeTask will get a Optional(someRunnable) value many times while the app is running, but most of the time the value is empty.

Should I maybe use a Supplier<Runnable> or Supplier<Optional<Runnable>> instead? If yes, how would you implement it? (I'm not so familiar with the Supplier class)

I'm open for any alternative (better) ways there achieve the same result.

Tagir Valeev
  • 97,161
  • 19
  • 222
  • 334
Nabuska
  • 443
  • 9
  • 17
  • 1
    What do you mean by "reset"? Do you want to make the Optional empty when the runnable is finished? If so, how are you running the runnable (please post the code where you do that)? – Tunaki Nov 17 '15 at 09:18
  • 3
    Your code wont compile as `oneTimeTask` is not effectively final (i.e. you assign it to something else inside lambda). – Jatin Nov 17 '15 at 09:39
  • Can you show us your use case because this question is a bit too broad. – Flown Nov 17 '15 at 09:55
  • http://stackoverflow.com/q/29132884/2711488 – Holger Nov 17 '15 at 12:08
  • Do you have one part of your application that produces these run-once tasks and another part runs them? – Misha Nov 17 '15 at 12:21

2 Answers2

4

As you want to control what is returned from one call to the next you want a Supplier.

AtomicBoolean once = new AtomicBoolean();
Supplier<Runnable> oneTimeTask = () -> once.getAndSet(true) 
                                     ? () -> {} 
                                     : () -> { /* do one */ };

or more simply you can have a Runnable

Runnable runs = () -> {
    if (once.getAndSet(true)) return;
    /* do once */
};
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • My code was written for android. I'm using 'me.tatarka.retrolambda' plugin that allows lambda expressions similar to Java 8 to be used with Android studio. But turns out there are some differences, such as in Java 8 it is not possible to modify a non static variable variable in a way that I did in my question above. – Nabuska Nov 18 '15 at 15:55
1

It looks like you are defining oneTimeTask as an instance or static field (otherwise it would have to be declared final to be accessible from your lambda). This is not the purpose of Optional.

Instead, you could simplify your code by keeping your field as a simple Runnable whose initial value is a no-op:

private Runnable oneTimeTask = () -> {};

And in your lambda, reset it to no-op when you are done:

oneTimeTask = () ->  {
        /*Run task
        ...*/
        oneTimeTask= () -> {};
    };

Now when you want to use it, you don't have to check whether it is null, nor to deal with the Optional api.

Community
  • 1
  • 1
Didier L
  • 18,905
  • 10
  • 61
  • 103
  • The code is for an Android app. I'm using a 'me.tatarka.retrolambda' plugin, and as it turns out it does not make the lambda expressions behave as in Java 8. Thank you for pointing this out. 'oneTimeTask' cannot be static in its purpose. I'll probably go with Peter Lawrey idea of using AtomicBoolean – Nabuska Nov 17 '15 at 19:17