System.out.printhoge()

コーディングの結構雑な学習メモ

Java8のラムダ式サンプル

https://github.com/taguro/SampleCode/blob/master/JavaLambdaSample.java

import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;


public class MainThread {

    public static void main(String[] args) {

        innerInterface test = ()->{System.out.println("hello");};
        test.express();

        //ラムダ式は、{}の外側で宣言している定数を参照できる
        String hoge ="{}の外側の定数";
        test = ()->{System.out.println(hoge);};
        test.express();

        //処理が1行の時は{}を省略できる
        String foo ="{}は省略OK";
        test = ()->System.out.println(foo);
        test.express();

        //もちろん引数を与えることもできる
        innerInterface2 test2 = (hoge2)->{System.out.println(hoge2);};
        test2.express("これは引数");

        //定義しないでも、引数を1つ受け取って、処理を行うためのインターフェースは用意されてる
        Consumer test3 = (hoge2)->{System.out.println(hoge2);};
        test3.accept("返り値のない処理にはConsumerを使おう");

        //引数を1つ受け取って値を返すためのインターフェース
        Function hogeCheck = (x)-> x == "hoge";
        if(hogeCheck.apply("hoge"))System.out.println("返り値のある処理にはFunctionを使おう");

        //引数を1つ受け取ってbooleanを返すインターフェースも既にある。他にも基本的なものは既にある。らしい。
        Predicate hogeCheck2 = (x)-> x == "hoge";
        if(hogeCheck2.test("hoge")){System.out.println("booleanを返す処理にはPredicateを使おう");}

        //上の例だとラムダ式(と無名クラス)のありがたさが分からないので、別のクラスに処理を埋め込む例
        String localVariable="この";
        innerClass3.showAfterCheck("別のクラスの処理に、このメソッドのローカル変数を組み込めた!", (x)->{return x.contains(localVariable);});

        //もちろん無名クラスを使って、こうすることもできる
        Predicate pred= new Predicate(){
            @Override
            public boolean test(String t) {
                return t.contains(localVariable);
            }
        };
        innerClass3.showAfterCheck("無名クラスを使ったこの方法もOK", pred);

        //無名クラスを使った方法を略記すると
        innerClass3.showAfterCheck("やっぱり無名クラスを使ったこの方法は少し書く文字が多い。new Predicateってわざわざ書きたくない", new Predicate(){
            @Override
            public boolean test(String t) {
                return t.contains(localVariable);
            }
        });

        //実用上はこんな使い方。短いので少し嬉しい。
        String str = "Threadでラムダ式";
        Thread thread = new Thread(()->{System.out.println(str);});
        thread.start();



        //おまけ:引数2つ以上使いたいときどうするか?
        //こうするとFunction hoge = (x,y)->{return x.equals(y);};エラーになる
        //C#だと引数2つ以上の時も、既に定義されている型Action(返り値なしの処理の場合)とFunc(返り値のある処理の場合)で
        //こんな風にFunc<引数1の型,引数2の型,返り値の型> hoge = (x,y)=>{return x.equals(y);} 宣言できるけれど、javaではダメらしい。
        //どうするかというと、innerInterface4みたいなの用意したり、List使うとかか。あるいは引数で渡すのは諦めてローカル変数を使う構成にするとか。
        innerInterface4 inner4 = (x,y,z)->{System.out.println(x+y+z);return x+y+z;};
        inner4.express("引数を複数与えるために、@FunctionalInterface", "を", "使う方法");

        ArrayList array = new ArrayList();
        array.add(3);
        array.add("3");
        Predicate test5 = (x)->{
            Object obj1 = x.get(0).toString();
            Object obj2 = (String)x.get(1);
            return obj1.equals(obj2);};
        if(test5.test(array)){System.out.println("ArrayListを使った方法も一応動く");}

    }

    //@FunctionalInterfaceというアノテーションを付けることで、ラムダ式のインターフェースを新たに定義できる
    @FunctionalInterface
    private interface innerInterface{
        public void express();
    }
    @FunctionalInterface
    private interface innerInterface2{
        public void express(String str);
    }

    @FunctionalInterface
    private interface innerInterface3{
        public void express(String str);
    }

    public static class innerClass3{
        public static void showAfterCheck(String str,Predicate pred){
            if(pred.test(str))System.out.println(str);
        }
    }

    @FunctionalInterface
    private interface innerInterface4{
        public String express(String str,String str2, String str3);
    }

}