65

I've got this code but IntelliJ tells me to replace anonymous with lambda but I don't know how. can anyone help me with this? Here is my code:

soundVolume.valueProperty().addListener(new ChangeListener<Number>() {
    public void changed(ObservableValue<? extends Number> ov,
                     Number old_val, Number new_val) {
        main.setSoundVolume(new_val.doubleValue());
        main.getMediaPlayer().setVolume(main.getSoundVolume());
    }
}); 
Michael
  • 41,989
  • 11
  • 82
  • 128
yukashima huksay
  • 5,834
  • 7
  • 45
  • 78

5 Answers5

113

Generally, something like this:

methodUsingYourClass(new YourClass() {
    public void uniqueMethod(Type1 parameter1, Type2 parameter2) {
        // body of function
    }
});

is replaced with

methodUsingYourClass((parameter1, parameter2) -> {
    // body of function
});

The types of the parameters can be inferred from usage, but there may be situations where specifying them is useful. This part from the above example

(parameter1, parameter2) -> {

would become this, if you decided to specify the types explicitly

(Type1 parameter1, Type2 parameter2) -> {

For your specific example, you can use:

soundVolume.valueProperty().addListener(
    (ov, old_val, new_val) -> {
        main.setSoundVolume(new_val.doubleValue());
        main.getMediaPlayer().setVolume(main.getSoundVolume());
    }
);

Note the replacement of an anonymous class with lambda is possible only if the anonymous class has one method. If the anonymous class has more methods then the substitution is not possible.

From the oracle documentation:

The previous section, Anonymous Classes, shows you how to implement a base class without giving it a name. Although this is often more concise than a named class, for classes with only one method, even an anonymous class seems a bit excessive and cumbersome. Lambda expressions let you express instances of single-method classes more compactly.

Michael
  • 41,989
  • 11
  • 82
  • 128
Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56
82

Why not let IntelliJ show you? Place your cursor on the declaration and press Alt + Enter (or Option + Enter if on a Mac) to bring up the intentions popup. Choose "Replace with lambda" and watch the transformed code...

Per Huss
  • 4,755
  • 12
  • 29
  • 5
    By the way; the same technique applies for most suggestions, I normally let the IDE transform the code for me if I agree with the suggestion... – Per Huss Jun 08 '16 at 07:14
9

for code clarity, you can also declare a variable with lambda and pass that variable to addListener method. for example

soundVolume.valueProperty().addListener(listener);

ChangeListener<Number> listener = (observable, oldValue, newValue) -> { ... };

Fahime Ghasemi
  • 775
  • 9
  • 13
2

It doesn't really help with the readability but here it is.

Note that main's reference should be final or effectively final for this to work.

soundVolume.valueProperty()
           .addListener(
           (ObservableValue<? extends Number> ov, Number old_val, Number new_val) -> {
               main.setSoundVolume(new_val.doubleValue());
               main.getMediaPlayer().setVolume(main.getSoundVolume())
           });
Yassin Hajaj
  • 21,337
  • 9
  • 51
  • 89
2

You can just right click on the element that gives you the warning, wait until the yellow balloon appears and choose, (replace with Lambda) and Android Studio will do it automatically.