April 16, 2014

Lambda Expression

Lambda Expression သည် Project Lambda မှ မွေးထုတ်လာခဲ့သော ရေးသားနည်း အသစ်တစ်မျိုးဖြစ်သည်။ Project Lambda ဟု ဆိုပါက Java SE 7 ကတည်းက ပါဝင်ရန်ကြိုးစားခဲ့သော်လည်း ယခု Java SE 8 ရောက်မှ Release လုပ်လာနိုင်ခဲ့ပါသည်။ ထို့အတွက်ကြောင့် Lambda Expression နှင့်ပတ်သက်၍ အဆိုပြုပုံအမျိုးမျိုး၊ ပြောင်းလည်းမှု့ အမျိုးမျိုးရှိခဲ့ကြပါသည်။ အဓိက အချက်တစ်ခုမှာ Lambda Expression သည် Object မဟုတ် ဆိုသည့်အချက်ပင် ဖြစ်သည်။

Lambda Expression အား ဖြည့်စွက်လာခြင်းကြောင့် Java သည် OOP မဟုတ်တော့၊ Functional Type Programming Language အဖြစ်ပြောင်းသွားမည်ဟု ထင်သည့်သူများလည်းရှိကြမည်။ သို့သော်လည်း Lambda Expression အား ဖြည့်စွက်လာခြင်းမှာ Parallel Programming များတွင် ပိုမိုလွယ်ကူ ရှင်းလင်းစွာ ရေးသားနိုင်ရန် ဖြစ်သည်။ အမှန်အတိုင်းပြောရလျှင် Functional Type Programming ဆိုသည်မှာ ပရိုဂရမ်ရေးသားသည့် Style တစ်ခု ဖြစ်သောကြောင့်၊ ရေးသောသော ပရိုဂရမ်မာအပေါ်တွင် မှုတည်ပါလိမ့်မည်။

Functional Type Programming Style ဖြင့်ရေးသားရန်မှာ First Class Method သည် မရှိမဖြစ်လိုအပ်ပါသည်။ သို့ရာတွင် Java SE 8 တွင်မှု FCM အား ထည့်သွင်းခဲ့ခြင်းမရှိပဲ လက်ရှိ နည်းလမ်းများဖြင့် အနီးစပ်ဆုံး အသုံးပြုနိုင်အောင် ဖန်တီးခဲ့ပါသည်။ ထို့ကြောင့် Java SE 8 သည် Functional Type Programming အား ရေးသားရလွယ်ကူလှသည်ဟုမဆိုနိုင်ပါ။ သို့ရာတွင် Lambda Expression အား ဖြည့်စွက်ခဲ့ခြင်းအားဖြင့် Functional Type Programming နှင့် အရင်ကထက်စာလျှင် ပို၍ နီးစပ်လာခဲ့ပါသည်။

Lambda Expression အကြောင်းမစသေးခင် အသုံးမပြုခင်ကနဲ့ ဘယ်လိုကွာတယ်ဆိုတာကို ကြည့်ပါမည်။
    public static void main(String[] args) {
        Runnable r = new Runnable() {
            
            @Override
            public void run() {
                System.out.println("Hello Java");
            }
        };
        
        r.run();
    }
Runnable Interface ၏ Object အား Anonymous Class ဖြင့် ရေးသားထားခြင်း ဖြစ်ပါသည်။ အတွင်းတွင် Run Method အား Override လုပ်၍ ရေးသားရပါမည်။ ၎င်းအား Lambda Expression အား အသုံးပြု၍ ရေးသားကြည့်ပါမည်။
    public static void main(String[] args) {
        Runnable r = () -> System.out.println("Hello Java");
        r.run();
    }
ဘာပဲပြောပြော စာကြောင်းရေအတော်နည်းပြီး အတော်လေးကို ရှင်းလင်းသွားပါသည်။ ဆက်လက်၍ Lambda Expression အား မည်သို့ရေးသားရသည်ဆိုသည်ကို လေ့လာသွားပါမည်။


Functional Type Interface


Interface တစ်ခုတွင် Implement လုပ်၍ ရေးသားရန် Method တစ်ခုသာပါသော Interface အား Functional Type Interface ဟု ခေါ်ပါသည်။ အထက်နမှုနာတွင် အသုံးပြုခဲ့သော Runnable သည် Functional Type Interface တစ်မျိုးဖြစ်ပါသည်။ အခြားသော Functional Type Interface များမှာ အောက်ပါအတိုင်း ဖြစ်ကြသည်။

  • java.util.concurrent.Callable
  • java.util.function.Consumer
  • javafx.event.EventHandler
အထက်ပါ Interface များသည် Functional Type Interface များဖြစ်ကြသည်။ Functional Type Interface ဟု သတ်မှတ်ရန် @FunctionalInterface အား  အသုံးပြု၍ ရေးသားနိုင်ပါသည်။

ထို့အပြင် Java SE 8 အရောက်တွင် Interface တွင် Default တန်ဖိုးများအား ရေးသားနိုင်ပြီး၊ ၎င်းအား Default Method ဟု ခေါ်ပါသည်။ နောက်ပိုင်းတွင် အသေးစိတ်ဖော်ပြသွားပါမည်။

Lambda Expression အား Functional Type Interface ၏ Anonymous Class ရေးသားရာတွင် အသုံးပြုပါသည်။


Lambda Expression


Lambda Expression အား ရေးသားရာတွင် အောက်ပါအတိုင်း ရေးသားနိုင်ပါသည်။
(argument) -> { Statement }
argument သည် Functional Type Interface ၏ Implement လုပ်ရန် လိုအပ်သော Method ၏ Argument ဖြစ်ပြီး၊ statement ၏ နေရာတွင် လုပ်ဆောင်ချက်များအား ရေးသားရပါမည်။
public class LambdaTest {
    
    @FunctionalInterface
    public interface AddNumber {
        public int add(int a, int b);
    }

    public static void main(String[] args) {
        AddNumber add = (int a, int b) -> {return a + b;};
        System.out.println(add.add(10, 3));
    }
}
အထက်ရေးသားပုံအတိုင်း Argument အား Interface အတိုင်း ရေးသားရပါသည်။ သို့ရာတွင် ဤကဲ့သို့ရေးသားရာတွင် Argument ၏ Type အား ရေးသားနေရသည်မှာ မလိုအပ်ပဲ ရှည်နေစေတတ်ပါသည်။ ထို့ကြောင့် Lambda Expression တွင် Argument Type အား မရေးသားပဲလည်း နေနိုင်ပါသည်။
    public static void main(String[] args) {
        AddNumber add = (a, b) -> {return a + b;};
        System.out.println(add.add(10, 3));
    }
အထက်ပါအတိုင်း Argument အား မရေးပဲလည်း ရေးသားနိုင်ပါသည်။ တစ်ခုသတိထားရန်မှာ Argument တစ်ခုအား Type ရေးပြီး၊ အခြားတစ်ခုအား မရေးပဲ နေ၍မရပေ။ မရေးသားပါက အားလုံးမရေးပဲ၊ ရေးပါက အားလုံး ရေးရန်လိုအပ်ပါသည်။

ထို့အပြင် Argument တစ်ခုတည်းဆိုပါက Argument ၏ Type ကော၊ Parameter ရေးသားရန် လက်သည်းကွင်းကိုပါ မရေးသားပဲ နေနိုင်ပါသည်။ သတိပြုရန်မှာ Type အား မရေးသားသောအခါမှ လက်သည်းကွင်းအား မရေးပဲနေနိုင်ခြင်း ဖြစ်ပါသည်။ Argument ၏ Type အား ရေးသားထားပါလျှက်နှင့် လက်သည်းကွင်းအား မရေးသား၍ မဖြစ်ပေ။
public class LambdaTest {
    
    @FunctionalInterface
    public interface Writer<T> {
        public void write(T t);
    }

    public static void main(String[] args) {
        Writer<String> writer = (text) -> {System.out.println(text);};
        writer.write("Hello Java");
    }
}
ထို့အပြင် Statement အား ရေးသားရာတွင် တစ်ကြောင်းတည်းဖြစ်ပါက အတွန့်ကွင်းကိုလည်း မရေးပဲ နေနိုင်ပါသည်။
public class LambdaTest {
    
    @FunctionalInterface
    public interface Writer<T> {
        public void write(T t);
    }

    public static void main(String[] args) {
        Writer<String> writer = text -> System.out.println(text);
        writer.write("Hello Java");
    }
}
အတွန့်ကွင်းအား မရေးသားထားပါက၊ return လုပ်ရမည့် method အတွက်လည်း return keyword အား ချိန်ထားခဲ့၍ ရပါသည်။
  Comparator comp1 = (x, y) -> { return x - y;};
  Comparator comp2 = (x, y) -> x - y;


သတိပြုရန်အချက်


အထက်တွင် Lambda Expression သည် Anonymous Class အား ရေးသားရန် အတိုနည်းဟု ဖော်ပြခဲ့သော်လည်း အနည်းငယ်ကွာခြားပါလိမ့်မည်။ ၎င်းမှာ this keyword ၏ အသုံးပြုပုံ ဖြစ်ပါသည်။ Anonymous Class တွင် this အား အသုံးပြုထားပါက Anonymous Class ၏ scope အား ဖော်ပြပြီး၊ Lambda Expression အတွင်း this အား အသုံးပြုပါက Lambda Expression အား ရေးသားထားသော Scope အား ညွှန်းပြပါသည်။
public class LambdaTest {
    
    @FunctionalInterface
    public interface ShowMessage {
        public void show(String message);
    }
    
    public LambdaTest() {
        ShowMessage m1 = new ShowMessage() {
            
            @Override
            public void show(String message) {
                System.out.println(message + " : " + this.getClass().getSimpleName());
            }
        };
        
        ShowMessage m2 = message -> System.out.println(message + " : " + this.getClass().getSimpleName());
        
        m1.show("From Anonymous");
        m2.show("From Lambda");
    }

    public static void main(String[] args) {
        new LambdaTest();
    }
}
အထက်ပါနမှုနာထဲတွင် m1 သည် ShowMessage Interface အား Anonymous Class ဖြင့် တည်ဆောက်ထားသော Object ဖြစ်ပြီး၊ ၎င်းအတွင်းတွင် show method အား Override လုပ်၍ ရေးသားထားပါသည်။ ၎င်းအတွင်းတွင် this.getClass အား ခေါ်ယူ အသုံးပြုထားပါသည်။

တဖန် m2 သည် ShowMessage Interface ၏ Object ဖြစ်ပြီး Lambda Expression အား ရေးသားထားပါသည်။ ၎င်းအတွင်းတွင်လည်း this.getClass method အား အသုံးပြုထားပါသည်။ အထက်ပါ နမှုနာအား Run ကြည့်ပါမည်။
From Anonymous : 
From Lambda : LambdaTest
အထက်ပါအတိုင်း Anonymous Class ၏ this သည် လက်ရှိ Anonymous Class ၏ Scope ကို ရည်ညွှန်းသောကြောင့် အမည်အား ဖော်ပြနိုင်ခြင်းမရှိပါ။ Lambda Expression အတွင်းမှမှု Lambda Expression အား ရေးသားထားသော LambdaTest Class အား ညွှန်းသောကြောင့် LambdaTest ဟု ဖော်ပြနေသည်ကို တွေ့ရပါသည်။

ကိုးကား
http://itpro.nikkeibp.co.jp/article/COLUMN/20140311/542582/?ST=develop&P=1


ဆက်ပါဦးမည်။ လေးစားစွာဖြင့်။
မင်းလွင်

No comments:

Post a Comment