Cara memetakan ekspresi lambda di Java

Saya berasal dari Python, dan mencoba memahami bagaimana ekspresi lambda bekerja secara berbeda di Java. Dengan Python, Anda dapat melakukan hal-hal seperti:

opdict = { "+":lambda a,b: a+b, "-": lambda a,b: a-b, 
           "*": lambda a,b: a*b, "/": lambda a,b: a/b }
sum = opdict["+"](5,4) 

Bagaimana saya bisa mencapai hal serupa di Jawa? Saya telah membaca sedikit tentang ekspresi lambda Java, dan sepertinya saya harus mendeklarasikan antarmuka terlebih dahulu, dan saya tidak jelas tentang bagaimana dan mengapa Anda perlu melakukan ini.

Sunting: Saya mencoba melakukan ini sendiri dengan antarmuka khusus. Inilah kode yang saya coba:

Map<String, MathOperation> opMap = new HashMap<String, MathOperation>(){
        { put("+",(a,b)->b+a);
          put("-",(a,b)->b-a);
          put("*",(a,b)->b*a);
          put("/",(a,b)->b/a); }
};
...
...

interface MathOperation {
   double operation(double a, double b);
}

Namun, ini memberikan kesalahan:

Tipe target ekspresi ini harus berupa antarmuka fungsional.

Di mana tepatnya saya mendeklarasikan antarmuka?


person b_pcakes    schedule 11.10.2015    source sumber


Jawaban (2)


Cukup mudah dilakukan dengan BiFunction di Java 8:

final Map<String, BiFunction<Integer, Integer, Integer>> opdict = new HashMap<>();
opdict.put("+", (x, y) -> x + y);
opdict.put("-", (x, y) -> x - y);
opdict.put("*", (x, y) -> x * y);
opdict.put("/", (x, y) -> x / y);

int sum = opdict.get("+").apply(5, 4);
System.out.println(sum);

Sintaksnya sedikit lebih bertele-tele daripada Python, dan menggunakan getOrDefault pada opdict mungkin lebih baik untuk menghindari skenario di mana Anda menggunakan operator yang tidak ada, tetapi ini setidaknya akan membuat bola bergulir.

Jika Anda secara eksklusif bekerja dengan ints, lebih baik menggunakan IntBinaryOperator, karena ini akan menangani pengetikan umum apa pun yang harus Anda lakukan.

final Map<String, IntBinaryOperator> opdict = new HashMap<>();
opdict.put("+", (x, y) -> x + y);
opdict.put("-", (x, y) -> x - y);
opdict.put("*", (x, y) -> x * y);
opdict.put("/", (x, y) -> x / y);

int sum = opdict.get("+").applyAsInt(5, 4);
System.out.println(sum);
person Makoto    schedule 11.10.2015
comment
IntBinaryOperator mungkin sedikit lebih baik. - person Paul Boddington; 12.10.2015
comment
@PaulBoddington: Ya, Anda memang benar, tapi kemudian kita mengalami skenario yang canggung: bagaimana jika kita ingin dapat menambahkan hal-hal yang bukan hanya int bersama-sama? Saya akan menyertakan apa yang telah Anda tunjukkan kepada saya, terima kasih untuk itu. - person Makoto; 12.10.2015
comment
Ya, skenario seperti itu bisa mengganggu, Ketika kita akhirnya mendapatkan Map.of("+", (x, y) -> x + y, "-", ..., ini akan hampir sama pendeknya dengan versi python. - person Paul Boddington; 12.10.2015
comment
Jawaban yang bagus, hanya satu pertanyaan lanjutan; Bagaimana saya melakukan ini jika saya ingin mengimplementasikan antarmuka saya sendiri? Menurut pemahaman saya, saat Anda membuat instance antarmuka menggunakan ekspresi lambda, pada dasarnya Anda mengimplementasikan metode abstrak antarmuka. Silakan lihat hasil edit yang saya buat pada postingan tersebut - person b_pcakes; 12.10.2015
comment
@SimonZhu: Saya tidak melihat adanya kegagalan kompilasi saat saya menggunakan antarmuka khusus Anda. Saya menjalankan Java terbaru (menurut saya) di 1.8.60; pastikan Anda juga up-to-date. - person Makoto; 12.10.2015

Solusi alternatif adalah dengan menggunakan enum:

public enum Operation {
    PLUS((x, y) -> x + y),
    MINUS((x, y) -> x - y),
    TIMES((x, y) -> x * y),
    DIVIDE((x, y) -> x / y);

    private final IntBinaryOperator op;

    Operation(IntBinaryOperator op) { this.op = op; }

    public int apply(int x, int y) { return op.applyAsInt(x, y); }
}

Kemudian Anda dapat melakukan:

int sum = Operation.PLUS.apply(5, 4);

Ini tidak sesingkat solusi lain, tetapi menggunakan enum daripada String berarti ketika Anda mengetik Operation. ke dalam IDE, Anda akan disajikan daftar semua kemungkinan operasi.

person Paul Boddington    schedule 11.10.2015