Functional Programming in Java 8

Java has introduced functional programming since 1.8, which is a big improvement. The advantage of functional programming is to improve coding efficiency and enhance code readability.

Functional programming essentially first takes functions as input parameters of methods . Since Java does not specify that functions or methods are a data type, it is necessary to use interfaces to express function parameters.

1. Lambda expression

By using anonymous inner classes in the sort method of the Arrays tool, not only can the amount of code be simplified, but also the continuity of the business can be maintained, but its structure is still verbose, and the code in the method body is still wordless, which still occupies several lines of code.

	Integer[] array = {
    
    83,86,95,2,4,99,55};
	// 匿名内部类无需专门定义形态完整的类,只需指明新创建的实例从哪个接口扩展而来
	Arrays.sort(array, new Comparator<Integer>() {
    
    
		public int compare(Integer o1, Integer o2) {
    
    
			return Integer.compare(o2, o1);
		}
	});

In order to further optimize the code, Lambda expression is actually an anonymous method , which refers to: a method without a name, but the internal code of the method body is complete .
In order to ensure that the actual body of the anonymous method is called, Java actually stipulates the following restrictions on its invocation :

  • Where an anonymous method is called, it must know the parameter type at that location;
  • The parameter type must be an interface, and the interface only declares an abstract method.

Lambda expressions are allowed only when the above two restrictions are met.

Feature mark of Lambda expression :Arrow sign "->".
The left side of the arrow is the parameter list of the anonymous method (if there are no input parameters in the anonymous method, a pair of parentheses should also be reserved.); the right side of the
arrow is the method body of the anonymous method .

Lambda体中的方法的参数列表和返回值要与所实现函数式接口的参数列表和返回值保持一致

According to the above two regulations, the comparison sorting method sort satisfies the first item, and the sorting comparator comparator satisfies the second item.

// Lambda表达式第一招。去掉了new、接口名称、方法名称
		Arrays.sort(intArray, (Integer o1, Integer o2) -> {
    
    
			return Integer.compare(o2, o1); // 按照降序排列
			});
// Lambda表达式第二招。去掉了输入参数的变量类型
		Arrays.sort(intArray, (o1, o2) -> {
    
    
			return Integer.compare(o2, o1); // 按照降序排列
			});
// Lambda表达式第三招。去掉了方法体的花括号,以及方法返回的return和分号
		Arrays.sort(intArray, (o1, o2) -> Integer.compare(o2, o1));

Summary: Use Lambda expressions to omit new, interface names, method names, variable types of input parameters, curly braces for method bodies, and return and semicolons returned by methods.

2. Functional interface definition

Since anonymous inner classes and Lambda expressions are attached to a certain interface, it is necessary to study the special features of this interface.

When I mentioned the concept of Lambda expressions, I mentioned that Lambda expressions refer to anonymous methods, and because Java does not support methods as parameter types, I had to add a layer of interface wrapper classes to the method, so I said before The parameter type in the sort method becomes the Comparator interface instead of the compare method.

As mentioned above, in order to distinguish other interfaces, Java named it " functional interface ". It has the form of a general interface, but it has one and only one abstract method inside. In addition, functional interfaces also allow definitions Other non-abstract methods, including default methods and static methods.

Next, take an animal class to understand the concept.

//定义一个行为接口,给动物类调用
public interface Behavior {
    
    
	public void act(); // 声明一个名叫行动的抽象方法
}

//演示动物类的定义,其中midnight方法的输入参数为Behavior类型
public class Animal {
    
    
	private String name; // 动物名称

	public Animal(String name) {
    
    
		this.name = name;
	}

	public String getName() {
    
    
		return this.name;
	}

	// 定义一个半夜行动的方法。具体的动作由输入行为的act方法执行
	public void midnight(Behavior behavior) {
    
    
		behavior.act();
	}

}
// 测试公鸡在半夜干了啥
	private static void testCock() {
    
    
		Animal cock = new Animal("公鸡"); // 创建一个公鸡实例
		// 调用midnight方法时,传入匿名内部类的实例
		/*cock.midnight(new Behavior() {
			@Override
			public void act() {
				System.out.println(cock.getName() + "在叫啦。");
			}
		});*/
		// 调用midnight方法时,传入Lambda表达式的代码。
		// 匿名方法不存在输入参数的话,也要保留一对圆括号占位子。
		cock.midnight(() -> System.out.println(cock.getName() + "在叫啦。"));
	}

Summary of the functional interface : The functional interface is suitable for situations where an external method is used as an input parameter. By using the functional interface, a group of instances can be individually passed in specific actions when invoking, instead of deriving many subclasses as before, and implementing their action methods in each subclass.

3. Method reference marked with double colon

Personal understanding: Method references are inherited from Lambda expressions. If the content in the Lambda expression has a method to achieve, then you can use the method reference. When there is only one method in the Lambda expression, you can use the method reference.

Reference method by a pair of double colon :: represented, method references a functional interface is another way of writing.

Three formats of method reference:

  • Instance name (object) :: method name
   public void Test1() {
    
    
   	//举例1
   	Consumer<String> con = (x) -> System.out.println(x);//使用Lambda表达式
   	con.accept("Hello");
   	Consumer<String> con1 = System.out::println;		//使用方法引用
   	con1.accept("World");
   	//举例2
   	Student student = new Student("Moti",10,"男");
   	Supplier<String> stuName = () -> student.getName();	//使用Lambda表达式
   	System.out.println(stuName.get());
   	Supplier<String> stuName1 = student::getName;		//使用方法引用
   	System.out.println(stuName1.get());
   }

operation result

Hello
World
Moti
Moti

It can be seen that the effect of using Lambda expressions and using method references is the same! Using method references will simplify the code more

  • Class name: static method name
	public void Test2() {
    
    
		Comparator<Integer> com = (x,y) -> Integer.compare(x, y);//使用Lambda表达式
		Comparator<Integer> com1 = Integer::compare;			 //使用方法引用
	}

  • Class name: instance method name
注意:
	Lambda体中的方法的参数列表和返回值要与所实现函数式接口的参数列表和返回值保持一致
	第一个参数是lambda体中方法的调用者,第二个参数是方法的参数时,可以使用	变量类型::实例方法名的方法引用
	public void Test3() {
    
    
		BiPredicate<String, String> bp = (x,y) -> x.equals(y);	 //使用Lambda表达式
		BiPredicate<String, String> bp1 = String::equals;		 //使用方法引用
	}

Guess you like

Origin blog.csdn.net/weixin_46312449/article/details/111590230