Java8 has been out for a long time, and many reports indicate that Java8 is a major release upgrade. This article mainly introduces lambda expressions.

Lambda expressions

Lambda expressions (also known as closures) are the biggest and most anticipated language change in Java 8. It allows us to pass functions as arguments to a method, or to treat the code itself as data: functional developers are familiar with these concepts.

Many languages on the JVM platform (Groovy, Scala, etc.) have supported Lambda expressions since their inception, but Java developers have had no choice but to use anonymous inner classes instead of Lambda expressions.

The design of Lambda took a lot of time and community effort to find a compromise that could achieve a concise and compact language structure. Lambda expressions need to be used in conjunction with functional interfaces.

1. Functional interfaces

Concept of 1.1.

A functional interface in Java is an interface that has only one abstract method. Functional interfaces, that is, interfaces suitable for functional programming scenarios. And functional programming in Java is Lambda, so functional interfaces are interfaces that can be used with Lambda. Lambdas in Java can only be derived smoothly by ensuring that there is one and only one abstract method in the interface. Note: “syntactic sugar” refers to code syntaxes that are more convenient to use, but the principle remains the same. For example, the for-each syntax is used when iterating through collections, but the underlying implementation principle is still iterators. This is syntactic sugar. At an application level, Lambdas in Java can be thought of as “syntactic sugar” for anonymous inner classes, but the two are different in principle.

1.2, the format

Just make sure there is one and only one abstract method in the interface:

1. Modifier interface Interface name {

2. Public abstract Return value type method name (optional parameter information).

3.}

1.3 @ FunctionalInterface annotation

Similar to the @Override annotation, a new annotation was introduced in Java 8 specifically for functional interfaces: @FunctionalInterface. This annotation can be used on the definition of an interface:

1. @FunctionalInterface

2. public interface MyFunctionalInterface {

3. void myMethod();

4.}

Once the annotation is used to define the interface, the compiler forces a check to see if the interface does have one and only one abstract method, or an error will be reported. Note that even if this annotation is not used, this is still a functional interface and works the same as long as it satisfies the definition of a functional interface.

2. Use of functional interfaces

2.1 Functional interface as parameter, method without parameter

1. // Define functional interfaces

2. public interface MyInterface{

3.

4. public abstract void show();

5.

6.}

7.

8. // Use (anonymous inner class object/function)

9. public class Demo01 {

10.

11. public static void main(String[] args) {

12. method01(new MyInterface01() {

13.

14. @Override

15. public void show() {

16. System.out.println(” Hello, functional interface “);

17.}

18.});

// Function

20. method01(() -> {

21. System.out.println(” Hello, functional interface “);

22.});

23. // Function shorthand (if there is only one line of code in the method body)

24. Method01 (() -> system.out.println (” Hello, functional interface “));

25.}

26.

27. public static void method01(MyInterface01 inter) {

28. inter.show();

29.}

30.

31.}

Advantages of functional interfaces

Functional interfaces produce fewer bytecode objects than anonymous inner class objects, improving Java execution efficiency.

2.2. Function interface as parameter, method with parameter

1. // Define functional interfaces

2. public interface MyInterface02 {

3.

4. public abstract void show(String msg1, String msg2);

5.

6.}

7.

8. // Use functional interfaces

9. public static void main(String[] args) {

// Anonymous inner class object

11. method01(new MyInterface02() {

12.

13. @Override

14. public void show(String msg1, String msg2) {

15. System.out.println(msg1 + msg2);

16.}

17.});

// The function is complete

19. method01((String msg1, String msg2) -> {

20. System.out.println(msg1 + msg2);

21.});

22. // Function shorthand

23. method01((msg1, msg2) -> System.out.println(msg1 + msg2));

24.

25.}

26.

27. public static void method01(MyInterface02 inter) {

28. Inter. Show (“hello”, “function “);

29.}

2.3. Function interface as return value, method without parameters

1. // Define functional interfaces

2. public interface MyInterface02 {

3.

4. public abstract void show(String msg1, String msg2);

5.

6.}

7. public static void main(String[] args) {

8.

9. GetInter1 ().show(” hello “, “functional “);

10. GetInter2 ().show(” hello “, “functional “);

11.

12.}

13.

// The function is complete

15. public static MyInterface02 getInter1() {

16.

17. return (String msg1, String msg2) -> {

18. System.out.println(msg1 + msg2);

19.};

20.}

21.

22. // Function shorthand

23. public static MyInterface02 getInter2() {

24.

25. return (msg1, msg2) -> System.out.println(msg1 + msg2);

26.}

3. Application scenarios of functional programming

Concept of 3.1,

While taking into account object-oriented features, the Java language uses functional interfaces through Lambda expressions, which is called functional programming

3.2. Use lambada as a parameter

Regardless of implementation principles, Lambda expressions in Java can be thought of as substitutes for anonymous inner classes. If the argument to a method is a functional interface type, Lambda expressions can be used instead.

1. public class Demo04Runnable{

2. private static void startThread(Runnable task){

3. new Thread(task).start();

4.}

5. public static void main(String[] args) {

6. StartThread (()‐> system.out.println (” thread execution “));

7.}

8.}

3.3. Use a functional interface as a return value

If the return type of a method is a functional interface, then a Lambda expression can be returned directly.

1. public class Demo06Comparator {

2.

3. private static Comparator<Integer> getComparator(){

4. Return (num1,num2)‐> num1-num2;

5.}

6.

7. public static void main(String[] args) {

8. Integer[] array = {3,2,1};

9. Arrays.sort(array, getComparator());

10. // Go through the number group

11.}

12.}

3.4, methods of functional interfaces have return values

1. public static void main(String[] args) {

2.

3. showMsg(new MyInterface03() {

4.

5. @Override

6. public String getMsg() {

7. return “hello functional interface”;

8.}

9.});

10.

11. // lambada expressions

12. showMsg(() -> {

13.

14. return “hello1 functional interface”;

15.});

16.

17. // Short for lambda expressions

18. showMsg(() -> “hello1 functional interface”);

19.

20.}

21.

22. public static void showMsg(MyInterface03 inter) {

23. String msg = inter.getMsg();

24. System.out.println(msg);

25.}

4. Supplier interface (Supplier interface)

The JDK provides a number of commonly used functional interfaces to enrich typical use scenarios for Lambda, mainly provided in the java.util.function package. The following are some simple interfaces and usage examples.

4.1: Supplier interface

Java. Util. Function. : Supplier < T > interface contains only a no arguments: T get (). Gets object data of the type specified by a generic parameter. Since this is a functional interface, this means that the corresponding Lambda expression needs to “supply” an object data that conforms to the generic type

4.2. Basic use

1. private static String getString(Supplier<String> function ){

2. return function.get();

3.}

4. public static void main(String[] args){

5. String msgA=”Hello”;

6. String msgB=”World”;

7. System.out.println(getString(()->msgA+msgB));

8.}

4.2. Comprehensive cases

Requirement: Find the maximum value in an int array using the Supplier interface as the method parameter type using a Lambda expression. Tip: Use the java.lang.Integer class for generics of the interface.

1. public static void main(String[] args) {

2. Integer max = getMax(()->{

3. Integer[] nums = {1,2,3,4};

4. int max2 = nums[0];

5. for (Integer num : nums) {

6. if(max2 < num){

7. max2 = num;

8.}

9.}

10. return max2;

11.});

12. System.out.println(max);

13.}

14.

15. public static Integer getMax(Supplier<Integer> supplier){

16. return supplier.get();

17.}

  

5. Common functional interfaces (Consumer interfaces)

5.1, the Consumer interface

Java. Util. The function. The Consumer < T > interface is just the opposite with: Supplier interface, it is not a production data, but the consumption of a data, the data type is determined by the generic

5.2, the accept method

The Consumer interface contains the abstract method void Accept (T T), which means consuming data of a specified generic type. Basic use such as:

1. public static void main(String[] args) {

2. consumeString((msg)->System.out.println(msg));

3.}

4.

5.

6. public static void consumeString(Consumer<String> consumer){

7. consumer.accept(“hello”);

8.}

5.3, andThen method

If the arguments and return values of a method are both of type Consumer, then you can achieve the effect of consuming data by first doing one operation and then doing another operation to implement the composition. That method is the default method andThen in the Consumer interface

1. default Consumer<T> andThen(Consumer<? super T> after) {

2. Objects.requireNonNull(after);

3. return (T t) -> { accept(t); after.accept(t); };

4.}

Note: The requireNonNull static method of java.util.Objects will actively throw a NullPointerException if the argument is null. This saves the trouble of repeatedly writing if statements and throwing null-pointer exceptions.

Requirement: Print uppercase HELLO first, then lowercase HELLO

1. public static void main(String[] args) {

2. consumeString((msg) -> System.out.println(msg.toUpperCase()),

3. (msg) -> System.out.println(msg.toLowerCase()));

4.}

5.

6. public static void consumeString(Consumer<String> consumer1, Consumer<String> consumer2) {

7. consumer1.andThen(consumer2).accept(“hello”);

8.}

6. Commonly used functional interfaces (Predicate interfaces)

Sometimes we need to evaluate certain types of data to get a Boolean result. Then you can use Java. Util. The function. The Predicate < T > interface

6.1, the test method

The Predicate interface contains an abstract method: Boolean test(T T). Scenarios for conditional judgment

1. public enum SingleClass06 {

2. INSTANCE;

3.}

6.2. Basic use

1. public static void main(String[] args) {

2. System.out.println(predicateTest((msg) -> msg.length() > 3, “hello”));

3.}

4.

5.

6. public static boolean predicateTest(Predicate<String> predicate,String msg){

7. return predicate.test(msg);

8.

9.}

7. To summarize

In this article, you learned about different ways to use lambda expressions, as well as some of the common functional interfaces that came with java8.0.