関数型インターフェースを使う際にいちいち関数を別の場所に用意するのが面倒な時があります。
一方「ラムダ式」を使えば処理内容を関数型インターフェースに直接代入できるので便利です。
ここではソースコードを見ながらラムダ式の具体的な使い方を説明します。

ラムダ式を考える前に、まず「ラムダ式を使わない」サンプルをソース1に示します。

ソース1: ラムダ式を使わないサンプル
import java.lang.Runnable;
import java.util.function.Function;
 
public class Main{

    public static void myrunnable1(){
        System.out.println("hoge");
    }

    public static void myrunnable2(){
        System.out.println("fuga");
    }

    public static String myfunction1( Integer a ){
        return "piyo="+a;
    }

    public static String myfunction2( Integer a ){
        return "foo="+a;
    }

    public static void main(String[] args) {

        Runnable runnable;
        Function< Integer, String > function;

        runnable = Main::myrunnable1;
        function = Main::myfunction1;

        runnable.run();
        System.out.println( function.apply( 123 ) );

        // 関数オブジェクトを再代入する
        runnable = Main::myrunnable2;
        function = Main::myfunction2;

        runnable.run();
        System.out.println( function.apply( 456 ) );
    }
}

ソース1の実行結果
hoge
piyo=123
fuga
foo=456

ではこのサンプルを「ラムダ式を使った」サンプルに修正してみましょう。
まずJavaのラムダ式の基本的な書式は次のようになります。
Java 以外のプログラミング言語でも似たような書き方をするので覚えておいて下さい。

ラムダ式の基本的な書式
(引数) -> {処理内容};

なお引数の型やラムダ式の戻り値の型を指定する必要はありません
この機能を「型推論」と呼びます。

このラムダ式を使ってソース1を書き直すと、次のソース2の様になります。

ソース2: ラムダ式を使ったサンプル
import java.lang.Runnable;
import java.util.function.Function;
 
public class Main{

    public static void main(String[] args) {

        Runnable runnable;
        Function< Integer, String > function;

        // ラムダ式を関数型インターフェースに代入
        runnable = () -> { System.out.println("hoge"); };
        function = (a) -> { return "piyo="+a; };

        runnable.run();
        System.out.println( function.apply( 123 ) );

        // ラムダ式を切り替える
        runnable = () -> { System.out.println("fuga"); };
        function = (a) -> { return "foo="+a; };

        runnable.run();
        System.out.println( function.apply( 456 ) );
    }
}

実行結果は同じなので省略します。
ソース1とソース2を見比べると、ラムダ式を使った方がコード量が減るのでスッキリしています。

さらに、引数が1つだけの場合は ()も省略できます(引数が無い場合や2つ以上の場合は省略不可)。
また、処理内容が 1 行だけの場合は中括弧や return を省略することが可能です。
例えばソース 2 のラムダ式を省略して書いたのが次のソース3です。

ソース3: ラムダ式を使ったサンプル (省略版)
import java.lang.Runnable;
import java.util.function.Function;
 
public class Main{

    public static void main(String[] args) {

        Runnable runnable;
        Function< Integer, String > function;

        // ラムダ式を関数型インターフェースに代入
        runnable = () -> System.out.println("hoge");  // 中括弧を省略
        function = a -> "piyo="+a;  // ()と中括弧と return を省略

        runnable.run();
        System.out.println( function.apply( 123 ) );

        // ラムダ式を切り替える
        runnable = () -> System.out.println("fuga"); // 中括弧を省略
        function = a -> "foo="+a; // ()と中括弧と return を省略

        runnable.run();
        System.out.println( function.apply( 456 ) );
    }
}

実行結果は同じなので省略します。
ソース2とソース3を見比べると更にスッキリしたことが分かります。

なお Java の場合は

ラムダ式の内部でローカル変数を使うとコンパイルエラーが出る

ので気をつけて下さい(ソース 4参考)。

ソース4: ラムダ式内でローカル変数を使うとコンパイルエラーが起きる

フィールドにはアクセス可能
※ final が付いていればローカル変数も参照可能

import java.lang.Runnable;
 
public class Main{

    public static void main(String[] args) {

        int a = 0;

        Runnable runnable;
        runnable = () -> a = 1;  // コンパイルエラー
    }
}