Functional interface for Lambda

In this blog, I would like to explain how Lambda functions work in Java, and how we can use them.

Functional interface

When talking about Lambda’s , the first thing to understand is the Functional Interface. As this is the sort of interface you would be using, when using Lambda’s. In fact Lambda’s define the implementation of a functional interface.

Java versions prior to 8 had SAM-interfaces : Single Abstract Method-interfaces. As the definition speaks for itself, it’s an interface with 1 abstract method. In Java 8, the concept of SAM-interfaces has been re-created and called “functional interfaces”.

You can write a functional interface yourself, but some already provided by the Java language via the java.util.function package, and used in different API’s.

  • Definition
    A functional interface is an interface with exactly 1 abstract method. The interface can have other methods, but they would have to be default methods, meaning that they would have their implementation in the interface itself. (This is also a new feature in Java 8.)
  • Example
    When writing a functional interface yourself, it’s a good practice to annotate it with @FunctionalInterface. This annotation is used to generate compiler level errors when the interface has more than 1 abstract method in your interface. The annotation is not required, but improves the readability of your code. For example:
    @FunctionalInterface
    interface Calculator {
    public double calculate(double val1, double val2);
    }
    
    If you would add another abstract method, you would get a compile time error: Invalid ‘@FunctionalInterface’ annotation; MyCalculator is not a functional interface
    We could add a few default method’s, and the interface will still remain a functional interface:
    @FunctionalInterface
    interface Calculator {
       public double calculate(double val1, double val2);
       default public void print(String str) {
          System.out.println("The print method prints "+str);
       }
       default public void print(double val1, double val2) {
          System.out.println("The print method prints "+val1+" "+val2);
       }
    }
    
    So we have written a functional interface with a method that takes a 2 doubles and returns a double. Now let’s create an implementation for this interface, the ‘old school’ way:
    Calculator multiply = new Calculator() {
        public double calculate(double val1, double val2) {
                return val1 * val2;
        }
    };
    Calculator sum = new Calculator() {
        public double calculate(double val1, double val2) {
                return val1 + val2;
        }
    };
    
    With Lamba functions it looks like this:
    Calculator multiply = (val1, val2) -> val1 * val2;
    Calculator sum = (val1, val2) -> val1 + val2;
    
    Notice that we removed the double declaration of the parameters, as the java compiler can defer those from the interface.
    Now let’s use our classes:
    System.out.println("multiply = "+multiply.calculate(5,6));
     This line executes 5*6, so it prints out “multiply = 30.0”
    
    System.out.println("sum = "+sum.calculate(5,6));
    this line executes 5+6, so it prints out “sum = 11.0”
    
  • The Java API way
    The java.util.function package contains functional interfaces that are used throughout the Java API. I’ll explain the Function, Consumer, Supplier, and Predicate as those are the ones that are mostly used in the Java API. We’ll use them in the next chapter where we demonstrate how to use them in the Stream API, an Java API that makes a lot of use of Lambda’s.

1.Function

So let’s start exploring the possibilities and usages of the lambda function’s in Java. As stated before, the java.util.function packages contains functional interfaces, and in this chapter I’d like to explain how to use them.
If you look at the abstract method of the Function interface, you see It looks like this: R apply(T t) . This method does nothing more then take an argument and returns a result. So we could write the following:

Function plus5 = (i -> i+5);
Integer var1 = plus5(1);

This function class will take an Integer, and return that integer+5. As we saw that the apply is the abstract function, i+5 is the implementation for that function. So that means that Line 2 will set var1 to 6. When we want more than 1 line code in the lamda function, we’ll need to use curly brackets.

Function plus5 = (i ->  { 
                System.out.println(" Integer=" + i);
               return i+5; 
});
Integer var1 = plus5(1);

If we execute the code on the last line, it will first, print ‘5’ to the console, and then, set integer var1 to 6.

Now that we know how to use a Function, let’s have a look at another interesting method in this interface :
default Function andThen(Function after)
This is a default method, meaning that it has its implementation in the Function interface class. Using this method, we can execute multiple functions in a chain. This is well illustrated when adding a print out in the Lamda.

Function plus5 = (i ->  { 
                System.out.println("Before plus 5 = " + i);
               return i+5;
         });
Function min2 = (i ->  { 
                System.out.println("Before min2 " + i);
               return i-5;
         });
Function plus10 = (i ->  { 
                System.out.println("Before plus10 " + i);
               return i+10;
         });
Integer var1 = plus5.andThen(min2).andThen(plus10).apply(100);
System.out.println("var1="+var1);

When executing this code, we’ll see the following output on the console :

Line 1 : before plus 5 = 100
Line 2 : before min2 105
Line 3 : before plus10 103
Line 4 : var1=113

So we execute plus5 with value 100, which prints Line 1.
andThen we execute min2 method (Line 2), entered with the new value 105 (5 added by the apply method)
andThen we execute plus10 method (Line 3), entered with the new value 103 (minus 2 by the first andThen method)
final result is 113, as 10 was added to 103 by the plus10.

2.Consumer

The java.util.function.Consumer interface is a bit like the Function, only it doesn’t returns any values. It just ‘consumes’ an object. Looking at the API, the abstract method is the following : void accept (T t) . So using our Lambda’s here:

Consumer printConsumer = str ->  System.out.println("str =" + str);
printConsumer.accept(“Hello Lambda”);

This will print: str=Hello Lambda
As you can see, we give the consumer a String as input, and it does something with it : print it out. As Function, the Consumer also has the ability to chain actions using a andThen method:

Consumer c1 = i ->  System.out.println("C1 Integer =" + i);
Consumer c2 = i ->  System.out.println("C2 Integer =" + (i+1));
Consumer c3 = i ->  System.out.println("C3 Integer =" + (i+5));
c1.andThen(c2).andThen(c2).andThen(c3).andThen(c2).accept(100);

This will print out the following to the console :

C1 Integer =100
C2 Integer =101
C2 Integer =101
C3 Integer =105
C2 Integer =101
First the accept of c1 is executed, then twice c2, adding 1 each time then C3, adding 5, and after c3 , c2 is executed again, adding 1.

3.Supplier

Next, we have the Supplier. This interface does not take any parameters, but only produces an output result.
Looking at the API we see following abstract method : T get() . Now here’s an example of a supplier, that supplies us with a random number:

Supplier random = () -> new Random().nextInt();
System.out.println("random integer:"+random.get());

This will print out the following to the console : random integer:1020054503
As there is no parameter passed to the method , we use the syntax “()” before the arrow to indicate this.

4.Predicate

Finally there is the Predicate interface. The abstract method here is boolean Test(T t) . So it takes an object, and returns a primitive Boolean.

Predicate equals5 = i -> i==5;
System.out.println("Is equal to 5 ? "+equals5.test(7));

This will print out the following to the console :Is equal to 5 ? false
Now we can also use this in a chain with and or or:

Predicate equals10 = i -> i==10;
System.out.println("Is equal to 5 or 10 ? "+equals5.or(equals10).test(5));

This will print out the following to the console : Is equal to 5 or 10 ? true

Conclusion

So in this article, I explained the very basics of Lambda functions. If you understand this, you’re ready for the great Lambda experience.
This is copied by Hugo from https://www.jstack.eu/blog. And also I don't wanna to translate it.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容